diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d774d8e..0788422 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,18 +1,22 @@ -name: make +name: go on: push: branches: - main pull_request: jobs: - build: + test: name: test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.19' - - run: wget https://github.com/tinygo-org/tinygo/releases/download/v0.26.0/tinygo_0.26.0_amd64.deb - - run: sudo dpkg -i tinygo_0.26.0_amd64.deb + go-version: '1.23.5' + - uses: sqlc-dev/setup-sqlc@v4 + with: + sqlc-version: '1.28.0' - run: make + - run: make test + - run: sqlc diff + working-directory: examples diff --git a/.github/workflows/db.yml b/.github/workflows/db.yml new file mode 100644 index 0000000..46d0115 --- /dev/null +++ b/.github/workflows/db.yml @@ -0,0 +1,44 @@ +name: db +on: + push: + branches: + - main + pull_request: +jobs: + + build: + name: test + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:11 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.9 + - name: Install python dependencies + working-directory: ./examples + run: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + - name: Test python code + working-directory: ./examples + env: + PG_USER: postgres + PG_HOST: localhost + PG_DATABASE: postgres + PG_PASSWORD: postgres + PG_PORT: ${{ job.services.postgres.ports['5432'] }} + run: | + pytest src/tests diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60b4f3d --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +bin + +# Devenv +.envrc +.direnv +.devenv* +devenv.local.nix diff --git a/LICENSE b/LICENSE index 8c50f0c..43c4c88 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Kyle Conroy +Copyright (c) 2023 Riza, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 0e47be8..d8ac60b 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,18 @@ -all: sqlc-gen-python +.PHONY: build test -sqlc-gen-python: - cd plugin && go build -o ~/bin/sqlc-gen-python ./main.go +build: + go build ./... -sqlc-gen-python.wasm: - cd plugin && tinygo build -o sqlc-gen-python.wasm -gc=leaking -scheduler=none -wasm-abi=generic -target=wasi main.go - openssl sha256 plugin/sqlc-gen-python.wasm +test: bin/sqlc-gen-python.wasm + go test ./... +all: bin/sqlc-gen-python bin/sqlc-gen-python.wasm + +bin/sqlc-gen-python: bin go.mod go.sum $(wildcard **/*.go) + cd plugin && go build -o ../bin/sqlc-gen-python ./main.go + +bin/sqlc-gen-python.wasm: bin/sqlc-gen-python + cd plugin && GOOS=wasip1 GOARCH=wasm go build -o ../bin/sqlc-gen-python.wasm main.go + +bin: + mkdir -p bin diff --git a/README.md b/README.md index 41acb7b..c9f2531 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,78 @@ ## Usage ```yaml -version: '2' +version: "2" plugins: -- name: py - wasm: - url: https://downloads.sqlc.dev/plugin/sqlc-gen-python_1.0.0.wasm - sha256: "FIXME" + - name: py + wasm: + url: https://downloads.sqlc.dev/plugin/sqlc-gen-python_1.3.0.wasm + sha256: fbedae96b5ecae2380a70fb5b925fd4bff58a6cfb1f3140375d098fbab7b3a3c sql: -- schema: "schema.sql" - queries: "query.sql" - engine: postgresql - codegen: - - out: src/authors - plugin: py - options: - package: authors - emit_sync_querier: true - emit_async_querier: true + - schema: "schema.sql" + queries: "query.sql" + engine: postgresql + codegen: + - out: src/authors + plugin: py + options: + package: authors + emit_sync_querier: true + emit_async_querier: true +``` + +### Emit Pydantic Models instead of `dataclasses` + +Option: `emit_pydantic_models` + +By default, `sqlc-gen-python` will emit `dataclasses` for the models. If you prefer to use [`pydantic`](https://docs.pydantic.dev/latest/) models, you can enable this option. + +with `emit_pydantic_models` + +```py +from pydantic import BaseModel + +class Author(pydantic.BaseModel): + id: int + name: str +``` + +without `emit_pydantic_models` + +```py +import dataclasses + +@dataclasses.dataclass() +class Author: + id: int + name: str +``` + +### Use `enum.StrEnum` for Enums + +Option: `emit_str_enum` + +`enum.StrEnum` was introduce in Python 3.11. + +`enum.StrEnum` is a subclass of `str` that is also a subclass of `Enum`. This allows for the use of `Enum` values as strings, compared to strings, or compared to other `enum.StrEnum` types. + +This is convenient for type checking and validation, as well as for serialization and deserialization. + +By default, `sqlc-gen-python` will emit `(str, enum.Enum)` for the enum classes. If you prefer to use `enum.StrEnum`, you can enable this option. + +with `emit_str_enum` + +```py +class Status(enum.StrEnum): + """Venues can be either open or closed""" + OPEN = "op!en" + CLOSED = "clo@sed" +``` + +without `emit_str_enum` (current behavior) + +```py +class Status(str, enum.Enum): + """Venues can be either open or closed""" + OPEN = "op!en" + CLOSED = "clo@sed" ``` diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 0000000..5c60f5d --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,7 @@ +version: v1 +managed: + enabled: true +plugins: + - plugin: buf.build/protocolbuffers/go:v1.30.0 + out: internal + opt: paths=source_relative diff --git a/buf.work.yaml b/buf.work.yaml new file mode 100644 index 0000000..4bddfe6 --- /dev/null +++ b/buf.work.yaml @@ -0,0 +1,3 @@ +version: v1 +directories: + - protos diff --git a/devenv.lock b/devenv.lock new file mode 100644 index 0000000..ea67978 --- /dev/null +++ b/devenv.lock @@ -0,0 +1,156 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1698243190, + "narHash": "sha256-n+SbyNQRhUcaZoU00d+7wi17HJpw/kAUrXOL4zRcqE8=", + "owner": "cachix", + "repo": "devenv", + "rev": "86f476f7edb86159fd20764489ab4e4df6edb4b6", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1685518550, + "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1698553279, + "narHash": "sha256-T/9P8yBSLcqo/v+FTOBK+0rjzjPMctVymZydbvR/Fak=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "90e85bc7c1a6fc0760a94ace129d3a1c61c3d035", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1685801374, + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1698227354, + "narHash": "sha256-Fi5H9jbaQLmLw9qBi/mkR33CoFjNbobo5xWdX4tKz1Q=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "bd38df3d508dfcdff52cd243d297f218ed2257bf", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 0000000..ca57de2 --- /dev/null +++ b/devenv.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: + +{ + # https://devenv.sh/packages/ + packages = [ + pkgs.go + pkgs.git + pkgs.govulncheck + pkgs.gopls + pkgs.golint + pkgs.python311 + ]; +} diff --git a/devenv.yaml b/devenv.yaml new file mode 100644 index 0000000..c7cb5ce --- /dev/null +++ b/devenv.yaml @@ -0,0 +1,3 @@ +inputs: + nixpkgs: + url: github:NixOS/nixpkgs/nixpkgs-unstable diff --git a/examples/requirements.txt b/examples/requirements.txt new file mode 100644 index 0000000..26f645a --- /dev/null +++ b/examples/requirements.txt @@ -0,0 +1,5 @@ +pytest~=6.2.2 +pytest-asyncio~=0.14.0 +psycopg2-binary~=2.8.6 +asyncpg~=0.21.0 +sqlalchemy==1.4.0 diff --git a/examples/sqlc.yaml b/examples/sqlc.yaml new file mode 100644 index 0000000..712c5db --- /dev/null +++ b/examples/sqlc.yaml @@ -0,0 +1,48 @@ +version: '2' +plugins: +- name: py + wasm: + url: https://downloads.sqlc.dev/plugin/sqlc-gen-python_1.2.0.wasm + sha256: a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e +sql: +- schema: "src/authors/schema.sql" + queries: "src/authors/query.sql" + engine: postgresql + codegen: + - out: src/authors + plugin: py + options: + package: authors + emit_sync_querier: true + emit_async_querier: true + query_parameter_limit: 5 +- schema: "src/booktest/schema.sql" + queries: "src/booktest/query.sql" + engine: postgresql + codegen: + - out: src/booktest + plugin: py + options: + package: booktest + emit_async_querier: true + query_parameter_limit: 5 +- schema: "src/jets/schema.sql" + queries: "src/jets/query-building.sql" + engine: postgresql + codegen: + - out: src/jets + plugin: py + options: + package: jets + emit_async_querier: true + query_parameter_limit: 5 +- schema: "src/ondeck/schema" + queries: "src/ondeck/query" + engine: postgresql + codegen: + - out: src/ondeck + plugin: py + options: + package: ondeck + emit_async_querier: true + query_parameter_limit: 5 diff --git a/examples/src/authors/__init__.py b/examples/src/authors/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/src/authors/models.py b/examples/src/authors/models.py new file mode 100644 index 0000000..96553a5 --- /dev/null +++ b/examples/src/authors/models.py @@ -0,0 +1,12 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses +from typing import Optional + + +@dataclasses.dataclass() +class Author: + id: int + name: str + bio: Optional[str] diff --git a/examples/src/authors/query.py b/examples/src/authors/query.py new file mode 100644 index 0000000..019f877 --- /dev/null +++ b/examples/src/authors/query.py @@ -0,0 +1,112 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +from typing import AsyncIterator, Iterator, Optional + +import sqlalchemy +import sqlalchemy.ext.asyncio + +from authors import models + + +CREATE_AUTHOR = """-- name: create_author \\:one +INSERT INTO authors ( + name, bio +) VALUES ( + :p1, :p2 +) +RETURNING id, name, bio +""" + + +DELETE_AUTHOR = """-- name: delete_author \\:exec +DELETE FROM authors +WHERE id = :p1 +""" + + +GET_AUTHOR = """-- name: get_author \\:one +SELECT id, name, bio FROM authors +WHERE id = :p1 LIMIT 1 +""" + + +LIST_AUTHORS = """-- name: list_authors \\:many +SELECT id, name, bio FROM authors +ORDER BY name +""" + + +class Querier: + def __init__(self, conn: sqlalchemy.engine.Connection): + self._conn = conn + + def create_author(self, *, name: str, bio: Optional[str]) -> Optional[models.Author]: + row = self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name, "p2": bio}).first() + if row is None: + return None + return models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + def delete_author(self, *, id: int) -> None: + self._conn.execute(sqlalchemy.text(DELETE_AUTHOR), {"p1": id}) + + def get_author(self, *, id: int) -> Optional[models.Author]: + row = self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": id}).first() + if row is None: + return None + return models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + def list_authors(self) -> Iterator[models.Author]: + result = self._conn.execute(sqlalchemy.text(LIST_AUTHORS)) + for row in result: + yield models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def create_author(self, *, name: str, bio: Optional[str]) -> Optional[models.Author]: + row = (await self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name, "p2": bio})).first() + if row is None: + return None + return models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + async def delete_author(self, *, id: int) -> None: + await self._conn.execute(sqlalchemy.text(DELETE_AUTHOR), {"p1": id}) + + async def get_author(self, *, id: int) -> Optional[models.Author]: + row = (await self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": id})).first() + if row is None: + return None + return models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + async def list_authors(self) -> AsyncIterator[models.Author]: + result = await self._conn.stream(sqlalchemy.text(LIST_AUTHORS)) + async for row in result: + yield models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) diff --git a/examples/src/authors/query.sql b/examples/src/authors/query.sql new file mode 100644 index 0000000..75e38b2 --- /dev/null +++ b/examples/src/authors/query.sql @@ -0,0 +1,19 @@ +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +) +RETURNING *; + +-- name: DeleteAuthor :exec +DELETE FROM authors +WHERE id = $1; diff --git a/examples/src/authors/schema.sql b/examples/src/authors/schema.sql new file mode 100644 index 0000000..b4fad78 --- /dev/null +++ b/examples/src/authors/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/examples/src/booktest/__init__.py b/examples/src/booktest/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/src/booktest/models.py b/examples/src/booktest/models.py new file mode 100644 index 0000000..d7ee131 --- /dev/null +++ b/examples/src/booktest/models.py @@ -0,0 +1,30 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses +import datetime +import enum +from typing import List + + +class BookType(str, enum.Enum): + FICTION = "FICTION" + NONFICTION = "NONFICTION" + + +@dataclasses.dataclass() +class Author: + author_id: int + name: str + + +@dataclasses.dataclass() +class Book: + book_id: int + author_id: int + isbn: str + book_type: BookType + title: str + year: int + available: datetime.datetime + tags: List[str] diff --git a/examples/src/booktest/query.py b/examples/src/booktest/query.py new file mode 100644 index 0000000..bc71f22 --- /dev/null +++ b/examples/src/booktest/query.py @@ -0,0 +1,211 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +import dataclasses +import datetime +from typing import AsyncIterator, List, Optional + +import sqlalchemy +import sqlalchemy.ext.asyncio + +from booktest import models + + +BOOKS_BY_TAGS = """-- name: books_by_tags \\:many +SELECT + book_id, + title, + name, + isbn, + tags +FROM books +LEFT JOIN authors ON books.author_id = authors.author_id +WHERE tags && :p1\\:\\:varchar[] +""" + + +@dataclasses.dataclass() +class BooksByTagsRow: + book_id: int + title: str + name: Optional[str] + isbn: str + tags: List[str] + + +BOOKS_BY_TITLE_YEAR = """-- name: books_by_title_year \\:many +SELECT book_id, author_id, isbn, book_type, title, year, available, tags FROM books +WHERE title = :p1 AND year = :p2 +""" + + +CREATE_AUTHOR = """-- name: create_author \\:one +INSERT INTO authors (name) VALUES (:p1) +RETURNING author_id, name +""" + + +CREATE_BOOK = """-- name: create_book \\:one +INSERT INTO books ( + author_id, + isbn, + book_type, + title, + year, + available, + tags +) VALUES ( + :p1, + :p2, + :p3, + :p4, + :p5, + :p6, + :p7 +) +RETURNING book_id, author_id, isbn, book_type, title, year, available, tags +""" + + +@dataclasses.dataclass() +class CreateBookParams: + author_id: int + isbn: str + book_type: models.BookType + title: str + year: int + available: datetime.datetime + tags: List[str] + + +DELETE_BOOK = """-- name: delete_book \\:exec +DELETE FROM books +WHERE book_id = :p1 +""" + + +GET_AUTHOR = """-- name: get_author \\:one +SELECT author_id, name FROM authors +WHERE author_id = :p1 +""" + + +GET_BOOK = """-- name: get_book \\:one +SELECT book_id, author_id, isbn, book_type, title, year, available, tags FROM books +WHERE book_id = :p1 +""" + + +UPDATE_BOOK = """-- name: update_book \\:exec +UPDATE books +SET title = :p1, tags = :p2 +WHERE book_id = :p3 +""" + + +UPDATE_BOOK_ISBN = """-- name: update_book_isbn \\:exec +UPDATE books +SET title = :p1, tags = :p2, isbn = :p4 +WHERE book_id = :p3 +""" + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def books_by_tags(self, *, dollar_1: List[str]) -> AsyncIterator[BooksByTagsRow]: + result = await self._conn.stream(sqlalchemy.text(BOOKS_BY_TAGS), {"p1": dollar_1}) + async for row in result: + yield BooksByTagsRow( + book_id=row[0], + title=row[1], + name=row[2], + isbn=row[3], + tags=row[4], + ) + + async def books_by_title_year(self, *, title: str, year: int) -> AsyncIterator[models.Book]: + result = await self._conn.stream(sqlalchemy.text(BOOKS_BY_TITLE_YEAR), {"p1": title, "p2": year}) + async for row in result: + yield models.Book( + book_id=row[0], + author_id=row[1], + isbn=row[2], + book_type=row[3], + title=row[4], + year=row[5], + available=row[6], + tags=row[7], + ) + + async def create_author(self, *, name: str) -> Optional[models.Author]: + row = (await self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name})).first() + if row is None: + return None + return models.Author( + author_id=row[0], + name=row[1], + ) + + async def create_book(self, arg: CreateBookParams) -> Optional[models.Book]: + row = (await self._conn.execute(sqlalchemy.text(CREATE_BOOK), { + "p1": arg.author_id, + "p2": arg.isbn, + "p3": arg.book_type, + "p4": arg.title, + "p5": arg.year, + "p6": arg.available, + "p7": arg.tags, + })).first() + if row is None: + return None + return models.Book( + book_id=row[0], + author_id=row[1], + isbn=row[2], + book_type=row[3], + title=row[4], + year=row[5], + available=row[6], + tags=row[7], + ) + + async def delete_book(self, *, book_id: int) -> None: + await self._conn.execute(sqlalchemy.text(DELETE_BOOK), {"p1": book_id}) + + async def get_author(self, *, author_id: int) -> Optional[models.Author]: + row = (await self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": author_id})).first() + if row is None: + return None + return models.Author( + author_id=row[0], + name=row[1], + ) + + async def get_book(self, *, book_id: int) -> Optional[models.Book]: + row = (await self._conn.execute(sqlalchemy.text(GET_BOOK), {"p1": book_id})).first() + if row is None: + return None + return models.Book( + book_id=row[0], + author_id=row[1], + isbn=row[2], + book_type=row[3], + title=row[4], + year=row[5], + available=row[6], + tags=row[7], + ) + + async def update_book(self, *, title: str, tags: List[str], book_id: int) -> None: + await self._conn.execute(sqlalchemy.text(UPDATE_BOOK), {"p1": title, "p2": tags, "p3": book_id}) + + async def update_book_isbn(self, *, title: str, tags: List[str], book_id: int, isbn: str) -> None: + await self._conn.execute(sqlalchemy.text(UPDATE_BOOK_ISBN), { + "p1": title, + "p2": tags, + "p3": book_id, + "p4": isbn, + }) diff --git a/examples/src/booktest/query.sql b/examples/src/booktest/query.sql new file mode 100644 index 0000000..194897a --- /dev/null +++ b/examples/src/booktest/query.sql @@ -0,0 +1,60 @@ +-- name: GetAuthor :one +SELECT * FROM authors +WHERE author_id = $1; + +-- name: GetBook :one +SELECT * FROM books +WHERE book_id = $1; + +-- name: DeleteBook :exec +DELETE FROM books +WHERE book_id = $1; + +-- name: BooksByTitleYear :many +SELECT * FROM books +WHERE title = $1 AND year = $2; + +-- name: BooksByTags :many +SELECT + book_id, + title, + name, + isbn, + tags +FROM books +LEFT JOIN authors ON books.author_id = authors.author_id +WHERE tags && $1::varchar[]; + +-- name: CreateAuthor :one +INSERT INTO authors (name) VALUES ($1) +RETURNING *; + +-- name: CreateBook :one +INSERT INTO books ( + author_id, + isbn, + book_type, + title, + year, + available, + tags +) VALUES ( + $1, + $2, + $3, + $4, + $5, + $6, + $7 +) +RETURNING *; + +-- name: UpdateBook :exec +UPDATE books +SET title = $1, tags = $2 +WHERE book_id = $3; + +-- name: UpdateBookISBN :exec +UPDATE books +SET title = $1, tags = $2, isbn = $4 +WHERE book_id = $3; diff --git a/examples/src/booktest/schema.sql b/examples/src/booktest/schema.sql new file mode 100644 index 0000000..2beecab --- /dev/null +++ b/examples/src/booktest/schema.sql @@ -0,0 +1,32 @@ +CREATE TABLE authors ( + author_id SERIAL PRIMARY KEY, + name text NOT NULL DEFAULT '' +); + +CREATE INDEX authors_name_idx ON authors(name); + +CREATE TYPE book_type AS ENUM ( + 'FICTION', + 'NONFICTION' +); + +CREATE TABLE books ( + book_id SERIAL PRIMARY KEY, + author_id integer NOT NULL REFERENCES authors(author_id), + isbn text NOT NULL DEFAULT '' UNIQUE, + book_type book_type NOT NULL DEFAULT 'FICTION', + title text NOT NULL DEFAULT '', + year integer NOT NULL DEFAULT 2000, + available timestamp with time zone NOT NULL DEFAULT 'NOW()', + tags varchar[] NOT NULL DEFAULT '{}' +); + +CREATE INDEX books_title_idx ON books(title, year); + +CREATE FUNCTION say_hello(text) RETURNS text AS $$ +BEGIN + RETURN CONCAT('hello ', $1); +END; +$$ LANGUAGE plpgsql; + +CREATE INDEX books_title_lower_idx ON books(title); diff --git a/examples/src/dbtest/__init__.py b/examples/src/dbtest/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/src/dbtest/migrations.py b/examples/src/dbtest/migrations.py new file mode 100644 index 0000000..6ace6bc --- /dev/null +++ b/examples/src/dbtest/migrations.py @@ -0,0 +1,43 @@ +import os +from typing import List + +import sqlalchemy +import sqlalchemy.ext.asyncio + + +def apply_migrations(conn: sqlalchemy.engine.Connection, paths: List[str]): + files = _find_sql_files(paths) + + for file in files: + with open(file, "r") as fd: + blob = fd.read() + stmts = blob.split(";") + for stmt in stmts: + if stmt.strip(): + conn.execute(sqlalchemy.text(stmt)) + + +async def apply_migrations_async(conn: sqlalchemy.ext.asyncio.AsyncConnection, paths: List[str]): + files = _find_sql_files(paths) + + for file in files: + with open(file, "r") as fd: + blob = fd.read() + raw_conn = await conn.get_raw_connection() + # The asyncpg sqlalchemy adapter uses a prepared statement cache which can't handle the migration statements + await raw_conn._connection.execute(blob) + + +def _find_sql_files(paths: List[str]) -> List[str]: + files = [] + for path in paths: + if not os.path.exists(path): + raise FileNotFoundError(f"{path} does not exist") + if os.path.isdir(path): + for file in os.listdir(path): + if file.endswith(".sql"): + files.append(os.path.join(path, file)) + else: + files.append(path) + files.sort() + return files diff --git a/examples/src/jets/__init__.py b/examples/src/jets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/src/jets/models.py b/examples/src/jets/models.py new file mode 100644 index 0000000..0d4eb5d --- /dev/null +++ b/examples/src/jets/models.py @@ -0,0 +1,31 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses + + +@dataclasses.dataclass() +class Jet: + id: int + pilot_id: int + age: int + name: str + color: str + + +@dataclasses.dataclass() +class Language: + id: int + language: str + + +@dataclasses.dataclass() +class Pilot: + id: int + name: str + + +@dataclasses.dataclass() +class PilotLanguage: + pilot_id: int + language_id: int diff --git a/examples/src/jets/query-building.py b/examples/src/jets/query-building.py new file mode 100644 index 0000000..7651116 --- /dev/null +++ b/examples/src/jets/query-building.py @@ -0,0 +1,47 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query-building.sql +from typing import AsyncIterator, Optional + +import sqlalchemy +import sqlalchemy.ext.asyncio + +from jets import models + + +COUNT_PILOTS = """-- name: count_pilots \\:one +SELECT COUNT(*) FROM pilots +""" + + +DELETE_PILOT = """-- name: delete_pilot \\:exec +DELETE FROM pilots WHERE id = :p1 +""" + + +LIST_PILOTS = """-- name: list_pilots \\:many +SELECT id, name FROM pilots LIMIT 5 +""" + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def count_pilots(self) -> Optional[int]: + row = (await self._conn.execute(sqlalchemy.text(COUNT_PILOTS))).first() + if row is None: + return None + return row[0] + + async def delete_pilot(self, *, id: int) -> None: + await self._conn.execute(sqlalchemy.text(DELETE_PILOT), {"p1": id}) + + async def list_pilots(self) -> AsyncIterator[models.Pilot]: + result = await self._conn.stream(sqlalchemy.text(LIST_PILOTS)) + async for row in result: + yield models.Pilot( + id=row[0], + name=row[1], + ) diff --git a/examples/src/jets/query-building.sql b/examples/src/jets/query-building.sql new file mode 100644 index 0000000..ede8952 --- /dev/null +++ b/examples/src/jets/query-building.sql @@ -0,0 +1,8 @@ +-- name: CountPilots :one +SELECT COUNT(*) FROM pilots; + +-- name: ListPilots :many +SELECT * FROM pilots LIMIT 5; + +-- name: DeletePilot :exec +DELETE FROM pilots WHERE id = $1; diff --git a/examples/src/jets/schema.sql b/examples/src/jets/schema.sql new file mode 100644 index 0000000..2cc4aca --- /dev/null +++ b/examples/src/jets/schema.sql @@ -0,0 +1,35 @@ +CREATE TABLE pilots ( + id integer NOT NULL, + name text NOT NULL +); + +ALTER TABLE pilots ADD CONSTRAINT pilot_pkey PRIMARY KEY (id); + +CREATE TABLE jets ( + id integer NOT NULL, + pilot_id integer NOT NULL, + age integer NOT NULL, + name text NOT NULL, + color text NOT NULL +); + +ALTER TABLE jets ADD CONSTRAINT jet_pkey PRIMARY KEY (id); +ALTER TABLE jets ADD CONSTRAINT jet_pilots_fkey FOREIGN KEY (pilot_id) REFERENCES pilots(id); + +CREATE TABLE languages ( + id integer NOT NULL, + language text NOT NULL +); + +ALTER TABLE languages ADD CONSTRAINT language_pkey PRIMARY KEY (id); + +-- Join table +CREATE TABLE pilot_languages ( + pilot_id integer NOT NULL, + language_id integer NOT NULL +); + +-- Composite primary key +ALTER TABLE pilot_languages ADD CONSTRAINT pilot_language_pkey PRIMARY KEY (pilot_id, language_id); +ALTER TABLE pilot_languages ADD CONSTRAINT pilot_language_pilots_fkey FOREIGN KEY (pilot_id) REFERENCES pilots(id); +ALTER TABLE pilot_languages ADD CONSTRAINT pilot_language_languages_fkey FOREIGN KEY (language_id) REFERENCES languages(id); diff --git a/examples/src/ondeck/__init__.py b/examples/src/ondeck/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/src/ondeck/city.py b/examples/src/ondeck/city.py new file mode 100644 index 0000000..5af93e9 --- /dev/null +++ b/examples/src/ondeck/city.py @@ -0,0 +1,76 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: city.sql +from typing import AsyncIterator, Optional + +import sqlalchemy +import sqlalchemy.ext.asyncio + +from ondeck import models + + +CREATE_CITY = """-- name: create_city \\:one +INSERT INTO city ( + name, + slug +) VALUES ( + :p1, + :p2 +) RETURNING slug, name +""" + + +GET_CITY = """-- name: get_city \\:one +SELECT slug, name +FROM city +WHERE slug = :p1 +""" + + +LIST_CITIES = """-- name: list_cities \\:many +SELECT slug, name +FROM city +ORDER BY name +""" + + +UPDATE_CITY_NAME = """-- name: update_city_name \\:exec +UPDATE city +SET name = :p2 +WHERE slug = :p1 +""" + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def create_city(self, *, name: str, slug: str) -> Optional[models.City]: + row = (await self._conn.execute(sqlalchemy.text(CREATE_CITY), {"p1": name, "p2": slug})).first() + if row is None: + return None + return models.City( + slug=row[0], + name=row[1], + ) + + async def get_city(self, *, slug: str) -> Optional[models.City]: + row = (await self._conn.execute(sqlalchemy.text(GET_CITY), {"p1": slug})).first() + if row is None: + return None + return models.City( + slug=row[0], + name=row[1], + ) + + async def list_cities(self) -> AsyncIterator[models.City]: + result = await self._conn.stream(sqlalchemy.text(LIST_CITIES)) + async for row in result: + yield models.City( + slug=row[0], + name=row[1], + ) + + async def update_city_name(self, *, slug: str, name: str) -> None: + await self._conn.execute(sqlalchemy.text(UPDATE_CITY_NAME), {"p1": slug, "p2": name}) diff --git a/examples/src/ondeck/models.py b/examples/src/ondeck/models.py new file mode 100644 index 0000000..1161408 --- /dev/null +++ b/examples/src/ondeck/models.py @@ -0,0 +1,35 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses +import datetime +import enum +from typing import List, Optional + + +class Status(str, enum.Enum): + """Venues can be either open or closed""" + OPEN = "op!en" + CLOSED = "clo@sed" + + +@dataclasses.dataclass() +class City: + slug: str + name: str + + +@dataclasses.dataclass() +class Venue: + """Venues are places where muisc happens""" + id: int + status: Status + statuses: Optional[List[Status]] + # This value appears in public URLs + slug: str + name: str + city: str + spotify_playlist: str + songkick_id: Optional[str] + tags: Optional[List[str]] + created_at: datetime.datetime diff --git a/examples/src/ondeck/query/city.sql b/examples/src/ondeck/query/city.sql new file mode 100644 index 0000000..f34dc99 --- /dev/null +++ b/examples/src/ondeck/query/city.sql @@ -0,0 +1,26 @@ +-- name: ListCities :many +SELECT * +FROM city +ORDER BY name; + +-- name: GetCity :one +SELECT * +FROM city +WHERE slug = $1; + +-- name: CreateCity :one +-- Create a new city. The slug must be unique. +-- This is the second line of the comment +-- This is the third line +INSERT INTO city ( + name, + slug +) VALUES ( + $1, + $2 +) RETURNING *; + +-- name: UpdateCityName :exec +UPDATE city +SET name = $2 +WHERE slug = $1; diff --git a/examples/src/ondeck/query/venue.sql b/examples/src/ondeck/query/venue.sql new file mode 100644 index 0000000..8c6bd02 --- /dev/null +++ b/examples/src/ondeck/query/venue.sql @@ -0,0 +1,49 @@ +-- name: ListVenues :many +SELECT * +FROM venue +WHERE city = $1 +ORDER BY name; + +-- name: DeleteVenue :exec +DELETE FROM venue +WHERE slug = $1 AND slug = $1; + +-- name: GetVenue :one +SELECT * +FROM venue +WHERE slug = $1 AND city = $2; + +-- name: CreateVenue :one +INSERT INTO venue ( + slug, + name, + city, + created_at, + spotify_playlist, + status, + statuses, + tags +) VALUES ( + $1, + $2, + $3, + NOW(), + $4, + $5, + $6, + $7 +) RETURNING id; + +-- name: UpdateVenueName :one +UPDATE venue +SET name = $2 +WHERE slug = $1 +RETURNING id; + +-- name: VenueCountByCity :many +SELECT + city, + count(*) +FROM venue +GROUP BY 1 +ORDER BY 1; diff --git a/examples/src/ondeck/schema/0001_city.sql b/examples/src/ondeck/schema/0001_city.sql new file mode 100644 index 0000000..af38f16 --- /dev/null +++ b/examples/src/ondeck/schema/0001_city.sql @@ -0,0 +1,4 @@ +CREATE TABLE city ( + slug text PRIMARY KEY, + name text NOT NULL +) diff --git a/examples/src/ondeck/schema/0002_venue.sql b/examples/src/ondeck/schema/0002_venue.sql new file mode 100644 index 0000000..940de7a --- /dev/null +++ b/examples/src/ondeck/schema/0002_venue.sql @@ -0,0 +1,18 @@ +CREATE TYPE status AS ENUM ('op!en', 'clo@sed'); +COMMENT ON TYPE status IS 'Venues can be either open or closed'; + +CREATE TABLE venues ( + id SERIAL primary key, + dropped text, + status status not null, + statuses status[], + slug text not null, + name varchar(255) not null, + city text not null references city(slug), + spotify_playlist varchar not null, + songkick_id text, + tags text[] +); +COMMENT ON TABLE venues IS 'Venues are places where muisc happens'; +COMMENT ON COLUMN venues.slug IS 'This value appears in public URLs'; + diff --git a/examples/src/ondeck/schema/0003_add_column.sql b/examples/src/ondeck/schema/0003_add_column.sql new file mode 100644 index 0000000..9b334bc --- /dev/null +++ b/examples/src/ondeck/schema/0003_add_column.sql @@ -0,0 +1,3 @@ +ALTER TABLE venues RENAME TO venue; +ALTER TABLE venue ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT NOW(); +ALTER TABLE venue DROP COLUMN dropped; diff --git a/examples/src/ondeck/venue.py b/examples/src/ondeck/venue.py new file mode 100644 index 0000000..6159bf6 --- /dev/null +++ b/examples/src/ondeck/venue.py @@ -0,0 +1,159 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: venue.sql +import dataclasses +from typing import AsyncIterator, List, Optional + +import sqlalchemy +import sqlalchemy.ext.asyncio + +from ondeck import models + + +CREATE_VENUE = """-- name: create_venue \\:one +INSERT INTO venue ( + slug, + name, + city, + created_at, + spotify_playlist, + status, + statuses, + tags +) VALUES ( + :p1, + :p2, + :p3, + NOW(), + :p4, + :p5, + :p6, + :p7 +) RETURNING id +""" + + +@dataclasses.dataclass() +class CreateVenueParams: + slug: str + name: str + city: str + spotify_playlist: str + status: models.Status + statuses: Optional[List[models.Status]] + tags: Optional[List[str]] + + +DELETE_VENUE = """-- name: delete_venue \\:exec +DELETE FROM venue +WHERE slug = :p1 AND slug = :p1 +""" + + +GET_VENUE = """-- name: get_venue \\:one +SELECT id, status, statuses, slug, name, city, spotify_playlist, songkick_id, tags, created_at +FROM venue +WHERE slug = :p1 AND city = :p2 +""" + + +LIST_VENUES = """-- name: list_venues \\:many +SELECT id, status, statuses, slug, name, city, spotify_playlist, songkick_id, tags, created_at +FROM venue +WHERE city = :p1 +ORDER BY name +""" + + +UPDATE_VENUE_NAME = """-- name: update_venue_name \\:one +UPDATE venue +SET name = :p2 +WHERE slug = :p1 +RETURNING id +""" + + +VENUE_COUNT_BY_CITY = """-- name: venue_count_by_city \\:many +SELECT + city, + count(*) +FROM venue +GROUP BY 1 +ORDER BY 1 +""" + + +@dataclasses.dataclass() +class VenueCountByCityRow: + city: str + count: int + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def create_venue(self, arg: CreateVenueParams) -> Optional[int]: + row = (await self._conn.execute(sqlalchemy.text(CREATE_VENUE), { + "p1": arg.slug, + "p2": arg.name, + "p3": arg.city, + "p4": arg.spotify_playlist, + "p5": arg.status, + "p6": arg.statuses, + "p7": arg.tags, + })).first() + if row is None: + return None + return row[0] + + async def delete_venue(self, *, slug: str) -> None: + await self._conn.execute(sqlalchemy.text(DELETE_VENUE), {"p1": slug}) + + async def get_venue(self, *, slug: str, city: str) -> Optional[models.Venue]: + row = (await self._conn.execute(sqlalchemy.text(GET_VENUE), {"p1": slug, "p2": city})).first() + if row is None: + return None + return models.Venue( + id=row[0], + status=row[1], + statuses=row[2], + slug=row[3], + name=row[4], + city=row[5], + spotify_playlist=row[6], + songkick_id=row[7], + tags=row[8], + created_at=row[9], + ) + + async def list_venues(self, *, city: str) -> AsyncIterator[models.Venue]: + result = await self._conn.stream(sqlalchemy.text(LIST_VENUES), {"p1": city}) + async for row in result: + yield models.Venue( + id=row[0], + status=row[1], + statuses=row[2], + slug=row[3], + name=row[4], + city=row[5], + spotify_playlist=row[6], + songkick_id=row[7], + tags=row[8], + created_at=row[9], + ) + + async def update_venue_name(self, *, slug: str, name: str) -> Optional[int]: + row = (await self._conn.execute(sqlalchemy.text(UPDATE_VENUE_NAME), {"p1": slug, "p2": name})).first() + if row is None: + return None + return row[0] + + async def venue_count_by_city(self) -> AsyncIterator[VenueCountByCityRow]: + result = await self._conn.stream(sqlalchemy.text(VENUE_COUNT_BY_CITY)) + async for row in result: + yield VenueCountByCityRow( + city=row[0], + count=row[1], + ) diff --git a/examples/src/tests/__init__.py b/examples/src/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/src/tests/conftest.py b/examples/src/tests/conftest.py new file mode 100644 index 0000000..f807209 --- /dev/null +++ b/examples/src/tests/conftest.py @@ -0,0 +1,67 @@ +import asyncio +import os +import random + +import pytest +import sqlalchemy +import sqlalchemy.ext.asyncio + + +@pytest.fixture(scope="session") +def postgres_uri() -> str: + pg_host = os.environ.get("PG_HOST", "postgres") + pg_port = os.environ.get("PG_PORT", 5432) + pg_user = os.environ.get("PG_USER", "postgres") + pg_password = os.environ.get("PG_PASSWORD", "mysecretpassword") + pg_db = os.environ.get("PG_DATABASE", "dinotest") + + return f"postgresql://{pg_user}:{pg_password}@{pg_host}:{pg_port}/{pg_db}" + + +@pytest.fixture(scope="session") +def sqlalchemy_connection(postgres_uri) -> sqlalchemy.engine.Connection: + engine = sqlalchemy.create_engine(postgres_uri, future=True) + with engine.connect() as conn: + yield conn + + +@pytest.fixture(scope="function") +def db(sqlalchemy_connection: sqlalchemy.engine.Connection) -> sqlalchemy.engine.Connection: + conn = sqlalchemy_connection + schema_name = f"sqltest_{random.randint(0, 1000)}" + conn.execute(sqlalchemy.text(f"CREATE SCHEMA {schema_name}")) + conn.execute(sqlalchemy.text(f"SET search_path TO {schema_name}")) + conn.commit() + yield conn + conn.rollback() + conn.execute(sqlalchemy.text(f"DROP SCHEMA {schema_name} CASCADE")) + conn.execute(sqlalchemy.text("SET search_path TO public")) + + +@pytest.fixture(scope="session") +async def async_sqlalchemy_connection(postgres_uri) -> sqlalchemy.ext.asyncio.AsyncConnection: + postgres_uri = postgres_uri.replace("postgresql", "postgresql+asyncpg") + engine = sqlalchemy.ext.asyncio.create_async_engine(postgres_uri) + async with engine.connect() as conn: + yield conn + + +@pytest.fixture(scope="function") +async def async_db(async_sqlalchemy_connection: sqlalchemy.ext.asyncio.AsyncConnection) -> sqlalchemy.ext.asyncio.AsyncConnection: + conn = async_sqlalchemy_connection + schema_name = f"sqltest_{random.randint(0, 1000)}" + await conn.execute(sqlalchemy.text(f"CREATE SCHEMA {schema_name}")) + await conn.execute(sqlalchemy.text(f"SET search_path TO {schema_name}")) + await conn.commit() + yield conn + await conn.rollback() + await conn.execute(sqlalchemy.text(f"DROP SCHEMA {schema_name} CASCADE")) + await conn.execute(sqlalchemy.text("SET search_path TO public")) + + +@pytest.fixture(scope="session") +def event_loop(): + """Change event_loop fixture to session level.""" + loop = asyncio.get_event_loop_policy().new_event_loop() + yield loop + loop.close() diff --git a/examples/src/tests/test_authors.py b/examples/src/tests/test_authors.py new file mode 100644 index 0000000..c3031cd --- /dev/null +++ b/examples/src/tests/test_authors.py @@ -0,0 +1,56 @@ +import os + +import pytest +import sqlalchemy.ext.asyncio + +from authors import query +from dbtest.migrations import apply_migrations, apply_migrations_async + + +def test_authors(db: sqlalchemy.engine.Connection): + apply_migrations(db, [os.path.dirname(__file__) + "/../authors/schema.sql"]) + + querier = query.Querier(db) + + authors = list(querier.list_authors()) + assert authors == [] + + author_name = "Brian Kernighan" + author_bio = "Co-author of The C Programming Language and The Go Programming Language" + new_author = querier.create_author(name=author_name, bio=author_bio) + assert new_author.id > 0 + assert new_author.name == author_name + assert new_author.bio == author_bio + + db_author = querier.get_author(id=new_author.id) + assert db_author == new_author + + author_list = list(querier.list_authors()) + assert len(author_list) == 1 + assert author_list[0] == new_author + + +@pytest.mark.asyncio +async def test_authors_async(async_db: sqlalchemy.ext.asyncio.AsyncConnection): + await apply_migrations_async(async_db, [os.path.dirname(__file__) + "/../authors/schema.sql"]) + + querier = query.AsyncQuerier(async_db) + + async for _ in querier.list_authors(): + assert False, "No authors should exist" + + author_name = "Brian Kernighan" + author_bio = "Co-author of The C Programming Language and The Go Programming Language" + new_author = await querier.create_author(name=author_name, bio=author_bio) + assert new_author.id > 0 + assert new_author.name == author_name + assert new_author.bio == author_bio + + db_author = await querier.get_author(id=new_author.id) + assert db_author == new_author + + author_list = [] + async for author in querier.list_authors(): + author_list.append(author) + assert len(author_list) == 1 + assert author_list[0] == new_author diff --git a/examples/src/tests/test_booktest.py b/examples/src/tests/test_booktest.py new file mode 100644 index 0000000..19959ae --- /dev/null +++ b/examples/src/tests/test_booktest.py @@ -0,0 +1,85 @@ +import datetime +import os + +import pytest +import sqlalchemy.ext.asyncio + +from booktest import query, models +from dbtest.migrations import apply_migrations_async + + +@pytest.mark.asyncio +async def test_books(async_db: sqlalchemy.ext.asyncio.AsyncConnection): + await apply_migrations_async(async_db, [os.path.dirname(__file__) + "/../booktest/schema.sql"]) + + querier = query.AsyncQuerier(async_db) + + author = await querier.create_author(name="Unknown Master") + assert author is not None + + now = datetime.datetime.now() + await querier.create_book(query.CreateBookParams( + author_id=author.author_id, + isbn="1", + title="my book title", + book_type=models.BookType.FICTION, + year=2016, + available=now, + tags=[], + )) + + b1 = await querier.create_book(query.CreateBookParams( + author_id=author.author_id, + isbn="2", + title="the second book", + book_type=models.BookType.FICTION, + year=2016, + available=now, + tags=["cool", "unique"], + )) + + await querier.update_book(book_id=b1.book_id, title="changed second title", tags=["cool", "disastor"]) + + b3 = await querier.create_book(query.CreateBookParams( + author_id=author.author_id, + isbn="3", + title="the third book", + book_type=models.BookType.FICTION, + year=2001, + available=now, + tags=["cool"], + )) + + b4 = await querier.create_book(query.CreateBookParams( + author_id=author.author_id, + isbn="4", + title="4th place finisher", + book_type=models.BookType.NONFICTION, + year=2011, + available=now, + tags=["other"], + )) + + await querier.update_book_isbn(book_id=b4.book_id, isbn="NEW ISBN", title="never ever gonna finish, a quatrain", tags=["someother"]) + + books0 = querier.books_by_title_year(title="my book title", year=2016) + expected_titles = {"my book title"} + async for book in books0: + expected_titles.remove(book.title) # raises a key error if the title does not exist + assert len(book.tags) == 0 + + author = await querier.get_author(author_id=book.author_id) + assert author.name == "Unknown Master" + assert len(expected_titles) == 0 + + books = querier.books_by_tags(dollar_1=["cool", "other", "someother"]) + expected_titles = {"changed second title", "the third book", "never ever gonna finish, a quatrain"} + async for book in books: + expected_titles.remove(book.title) + assert len(expected_titles) == 0 + + b5 = await querier.get_book(book_id=b3.book_id) + assert b5 is not None + await querier.delete_book(book_id=b5.book_id) + b6 = await querier.get_book(book_id=b5.book_id) + assert b6 is None diff --git a/examples/src/tests/test_ondeck.py b/examples/src/tests/test_ondeck.py new file mode 100644 index 0000000..20185a8 --- /dev/null +++ b/examples/src/tests/test_ondeck.py @@ -0,0 +1,53 @@ +import os + +import pytest +import sqlalchemy.ext.asyncio + +from ondeck import models +from ondeck import city as city_queries +from ondeck import venue as venue_queries +from dbtest.migrations import apply_migrations_async + + +@pytest.mark.asyncio +async def test_ondeck(async_db: sqlalchemy.ext.asyncio.AsyncConnection): + await apply_migrations_async(async_db, [os.path.dirname(__file__) + "/../ondeck/schema"]) + + city_querier = city_queries.AsyncQuerier(async_db) + venue_querier = venue_queries.AsyncQuerier(async_db) + + city = await city_querier.create_city(slug="san-francisco", name="San Francisco") + assert city is not None + + venue_id = await venue_querier.create_venue(venue_queries.CreateVenueParams( + slug="the-fillmore", + name="The Fillmore", + city=city.slug, + spotify_playlist="spotify:uri", + status=models.Status.OPEN, + statuses=[models.Status.OPEN, models.Status.CLOSED], + tags=["rock", "punk"], + )) + assert venue_id is not None + + venue = await venue_querier.get_venue(slug="the-fillmore", city=city.slug) + assert venue is not None + assert venue.id == venue_id + + assert city == await city_querier.get_city(slug=city.slug) + assert [venue_queries.VenueCountByCityRow(city=city.slug, count=1)] == await _to_list(venue_querier.venue_count_by_city()) + assert [city] == await _to_list(city_querier.list_cities()) + assert [venue] == await _to_list(venue_querier.list_venues(city=city.slug)) + + await city_querier.update_city_name(slug=city.slug, name="SF") + _id = await venue_querier.update_venue_name(slug=venue.slug, name="Fillmore") + assert _id == venue_id + + await venue_querier.delete_venue(slug=venue.slug) + + +async def _to_list(it): + out = [] + async for i in it: + out.append(i) + return out diff --git a/go.mod b/go.mod index 379ab3e..f8363d2 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,19 @@ -module github.com/tabbed/sqlc-gen-python +module github.com/sqlc-dev/sqlc-gen-python go 1.19 require ( - github.com/google/go-cmp v0.5.9 + github.com/google/go-cmp v0.6.0 github.com/jinzhu/inflection v1.0.0 - github.com/mailru/easyjson v0.7.7 - github.com/tabbed/sqlc-go v0.0.0-20221009183118-d55f5a939a05 - google.golang.org/protobuf v1.28.1 + github.com/sqlc-dev/plugin-sdk-go v1.23.0 + google.golang.org/protobuf v1.34.2 ) -require github.com/josharian/intern v1.0.0 // indirect +require ( + github.com/golang/protobuf v1.5.3 // indirect + golang.org/x/net v0.14.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/grpc v1.59.0 // indirect +) diff --git a/go.sum b/go.sum index 801a94a..9b82ab2 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,25 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/tabbed/sqlc-go v0.0.0-20221009183118-d55f5a939a05 h1:Iek16hHBI+jpwSZr5++IQJxzUrBCVJN6dAJ3cdORSX4= -github.com/tabbed/sqlc-go v0.0.0-20221009183118-d55f5a939a05/go.mod h1:BRbblaIKvbUfZT43OSS2CWoitiad1DJ4osdciynXLyA= +github.com/sqlc-dev/plugin-sdk-go v1.23.0 h1:iSeJhnXPlbDXlbzUEebw/DxsGzE9rdDJArl8Hvt0RMM= +github.com/sqlc-dev/plugin-sdk-go v1.23.0/go.mod h1:I1r4THOfyETD+LI2gogN2LX8wCjwUZrgy/NU4In3llA= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/internal/ast/ast.pb.go b/internal/ast/ast.pb.go index b170509..b0b1d3a 100644 --- a/internal/ast/ast.pb.go +++ b/internal/ast/ast.pb.go @@ -1,14 +1,15 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.6.1 -// source: python/ast.proto +// protoc-gen-go v1.30.0 +// protoc (unknown) +// source: ast/ast.proto package ast import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" sync "sync" ) @@ -25,6 +26,7 @@ type Node struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Node: + // // *Node_ClassDef // *Node_Import // *Node_ImportFrom @@ -61,7 +63,7 @@ type Node struct { func (x *Node) Reset() { *x = Node{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[0] + mi := &file_ast_ast_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -74,7 +76,7 @@ func (x *Node) String() string { func (*Node) ProtoMessage() {} func (x *Node) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[0] + mi := &file_ast_ast_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -87,7 +89,7 @@ func (x *Node) ProtoReflect() protoreflect.Message { // Deprecated: Use Node.ProtoReflect.Descriptor instead. func (*Node) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{0} + return file_ast_ast_proto_rawDescGZIP(), []int{0} } func (m *Node) GetNode() isNode_Node { @@ -502,7 +504,7 @@ type Alias struct { func (x *Alias) Reset() { *x = Alias{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[1] + mi := &file_ast_ast_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -515,7 +517,7 @@ func (x *Alias) String() string { func (*Alias) ProtoMessage() {} func (x *Alias) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[1] + mi := &file_ast_ast_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -528,7 +530,7 @@ func (x *Alias) ProtoReflect() protoreflect.Message { // Deprecated: Use Alias.ProtoReflect.Descriptor instead. func (*Alias) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{1} + return file_ast_ast_proto_rawDescGZIP(), []int{1} } func (x *Alias) GetName() string { @@ -549,7 +551,7 @@ type Await struct { func (x *Await) Reset() { *x = Await{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[2] + mi := &file_ast_ast_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -562,7 +564,7 @@ func (x *Await) String() string { func (*Await) ProtoMessage() {} func (x *Await) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[2] + mi := &file_ast_ast_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -575,7 +577,7 @@ func (x *Await) ProtoReflect() protoreflect.Message { // Deprecated: Use Await.ProtoReflect.Descriptor instead. func (*Await) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{2} + return file_ast_ast_proto_rawDescGZIP(), []int{2} } func (x *Await) GetValue() *Node { @@ -597,7 +599,7 @@ type Attribute struct { func (x *Attribute) Reset() { *x = Attribute{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[3] + mi := &file_ast_ast_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -610,7 +612,7 @@ func (x *Attribute) String() string { func (*Attribute) ProtoMessage() {} func (x *Attribute) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[3] + mi := &file_ast_ast_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -623,7 +625,7 @@ func (x *Attribute) ProtoReflect() protoreflect.Message { // Deprecated: Use Attribute.ProtoReflect.Descriptor instead. func (*Attribute) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{3} + return file_ast_ast_proto_rawDescGZIP(), []int{3} } func (x *Attribute) GetValue() *Node { @@ -654,7 +656,7 @@ type AnnAssign struct { func (x *AnnAssign) Reset() { *x = AnnAssign{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[4] + mi := &file_ast_ast_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -667,7 +669,7 @@ func (x *AnnAssign) String() string { func (*AnnAssign) ProtoMessage() {} func (x *AnnAssign) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[4] + mi := &file_ast_ast_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -680,7 +682,7 @@ func (x *AnnAssign) ProtoReflect() protoreflect.Message { // Deprecated: Use AnnAssign.ProtoReflect.Descriptor instead. func (*AnnAssign) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{4} + return file_ast_ast_proto_rawDescGZIP(), []int{4} } func (x *AnnAssign) GetTarget() *Name { @@ -723,7 +725,7 @@ type Arg struct { func (x *Arg) Reset() { *x = Arg{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[5] + mi := &file_ast_ast_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -736,7 +738,7 @@ func (x *Arg) String() string { func (*Arg) ProtoMessage() {} func (x *Arg) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[5] + mi := &file_ast_ast_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -749,7 +751,7 @@ func (x *Arg) ProtoReflect() protoreflect.Message { // Deprecated: Use Arg.ProtoReflect.Descriptor instead. func (*Arg) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{5} + return file_ast_ast_proto_rawDescGZIP(), []int{5} } func (x *Arg) GetArg() string { @@ -778,7 +780,7 @@ type Arguments struct { func (x *Arguments) Reset() { *x = Arguments{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[6] + mi := &file_ast_ast_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -791,7 +793,7 @@ func (x *Arguments) String() string { func (*Arguments) ProtoMessage() {} func (x *Arguments) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[6] + mi := &file_ast_ast_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -804,7 +806,7 @@ func (x *Arguments) ProtoReflect() protoreflect.Message { // Deprecated: Use Arguments.ProtoReflect.Descriptor instead. func (*Arguments) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{6} + return file_ast_ast_proto_rawDescGZIP(), []int{6} } func (x *Arguments) GetArgs() []*Arg { @@ -834,7 +836,7 @@ type AsyncFor struct { func (x *AsyncFor) Reset() { *x = AsyncFor{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[7] + mi := &file_ast_ast_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -847,7 +849,7 @@ func (x *AsyncFor) String() string { func (*AsyncFor) ProtoMessage() {} func (x *AsyncFor) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[7] + mi := &file_ast_ast_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -860,7 +862,7 @@ func (x *AsyncFor) ProtoReflect() protoreflect.Message { // Deprecated: Use AsyncFor.ProtoReflect.Descriptor instead. func (*AsyncFor) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{7} + return file_ast_ast_proto_rawDescGZIP(), []int{7} } func (x *AsyncFor) GetTarget() *Node { @@ -898,7 +900,7 @@ type AsyncFunctionDef struct { func (x *AsyncFunctionDef) Reset() { *x = AsyncFunctionDef{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[8] + mi := &file_ast_ast_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -911,7 +913,7 @@ func (x *AsyncFunctionDef) String() string { func (*AsyncFunctionDef) ProtoMessage() {} func (x *AsyncFunctionDef) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[8] + mi := &file_ast_ast_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -924,7 +926,7 @@ func (x *AsyncFunctionDef) ProtoReflect() protoreflect.Message { // Deprecated: Use AsyncFunctionDef.ProtoReflect.Descriptor instead. func (*AsyncFunctionDef) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{8} + return file_ast_ast_proto_rawDescGZIP(), []int{8} } func (x *AsyncFunctionDef) GetName() string { @@ -968,7 +970,7 @@ type Assign struct { func (x *Assign) Reset() { *x = Assign{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[9] + mi := &file_ast_ast_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -981,7 +983,7 @@ func (x *Assign) String() string { func (*Assign) ProtoMessage() {} func (x *Assign) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[9] + mi := &file_ast_ast_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -994,7 +996,7 @@ func (x *Assign) ProtoReflect() protoreflect.Message { // Deprecated: Use Assign.ProtoReflect.Descriptor instead. func (*Assign) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{9} + return file_ast_ast_proto_rawDescGZIP(), []int{9} } func (x *Assign) GetTargets() []*Node { @@ -1031,7 +1033,7 @@ type Call struct { func (x *Call) Reset() { *x = Call{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[10] + mi := &file_ast_ast_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1044,7 +1046,7 @@ func (x *Call) String() string { func (*Call) ProtoMessage() {} func (x *Call) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[10] + mi := &file_ast_ast_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1057,7 +1059,7 @@ func (x *Call) ProtoReflect() protoreflect.Message { // Deprecated: Use Call.ProtoReflect.Descriptor instead. func (*Call) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{10} + return file_ast_ast_proto_rawDescGZIP(), []int{10} } func (x *Call) GetFunc() *Node { @@ -1096,7 +1098,7 @@ type ClassDef struct { func (x *ClassDef) Reset() { *x = ClassDef{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[11] + mi := &file_ast_ast_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1109,7 +1111,7 @@ func (x *ClassDef) String() string { func (*ClassDef) ProtoMessage() {} func (x *ClassDef) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[11] + mi := &file_ast_ast_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1122,7 +1124,7 @@ func (x *ClassDef) ProtoReflect() protoreflect.Message { // Deprecated: Use ClassDef.ProtoReflect.Descriptor instead. func (*ClassDef) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{11} + return file_ast_ast_proto_rawDescGZIP(), []int{11} } func (x *ClassDef) GetName() string { @@ -1173,7 +1175,7 @@ type Comment struct { func (x *Comment) Reset() { *x = Comment{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[12] + mi := &file_ast_ast_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1186,7 +1188,7 @@ func (x *Comment) String() string { func (*Comment) ProtoMessage() {} func (x *Comment) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[12] + mi := &file_ast_ast_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1199,7 +1201,7 @@ func (x *Comment) ProtoReflect() protoreflect.Message { // Deprecated: Use Comment.ProtoReflect.Descriptor instead. func (*Comment) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{12} + return file_ast_ast_proto_rawDescGZIP(), []int{12} } func (x *Comment) GetText() string { @@ -1222,7 +1224,7 @@ type Compare struct { func (x *Compare) Reset() { *x = Compare{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[13] + mi := &file_ast_ast_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1235,7 +1237,7 @@ func (x *Compare) String() string { func (*Compare) ProtoMessage() {} func (x *Compare) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[13] + mi := &file_ast_ast_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1248,7 +1250,7 @@ func (x *Compare) ProtoReflect() protoreflect.Message { // Deprecated: Use Compare.ProtoReflect.Descriptor instead. func (*Compare) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{13} + return file_ast_ast_proto_rawDescGZIP(), []int{13} } func (x *Compare) GetLeft() *Node { @@ -1278,6 +1280,7 @@ type Constant struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Value: + // // *Constant_Str // *Constant_Int // *Constant_None @@ -1287,7 +1290,7 @@ type Constant struct { func (x *Constant) Reset() { *x = Constant{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[14] + mi := &file_ast_ast_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1300,7 +1303,7 @@ func (x *Constant) String() string { func (*Constant) ProtoMessage() {} func (x *Constant) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[14] + mi := &file_ast_ast_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1313,7 +1316,7 @@ func (x *Constant) ProtoReflect() protoreflect.Message { // Deprecated: Use Constant.ProtoReflect.Descriptor instead. func (*Constant) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{14} + return file_ast_ast_proto_rawDescGZIP(), []int{14} } func (m *Constant) GetValue() isConstant_Value { @@ -1378,7 +1381,7 @@ type Dict struct { func (x *Dict) Reset() { *x = Dict{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[15] + mi := &file_ast_ast_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1391,7 +1394,7 @@ func (x *Dict) String() string { func (*Dict) ProtoMessage() {} func (x *Dict) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[15] + mi := &file_ast_ast_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1404,7 +1407,7 @@ func (x *Dict) ProtoReflect() protoreflect.Message { // Deprecated: Use Dict.ProtoReflect.Descriptor instead. func (*Dict) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{15} + return file_ast_ast_proto_rawDescGZIP(), []int{15} } func (x *Dict) GetKeys() []*Node { @@ -1432,7 +1435,7 @@ type Expr struct { func (x *Expr) Reset() { *x = Expr{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[16] + mi := &file_ast_ast_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1445,7 +1448,7 @@ func (x *Expr) String() string { func (*Expr) ProtoMessage() {} func (x *Expr) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[16] + mi := &file_ast_ast_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1458,7 +1461,7 @@ func (x *Expr) ProtoReflect() protoreflect.Message { // Deprecated: Use Expr.ProtoReflect.Descriptor instead. func (*Expr) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{16} + return file_ast_ast_proto_rawDescGZIP(), []int{16} } func (x *Expr) GetValue() *Node { @@ -1481,7 +1484,7 @@ type For struct { func (x *For) Reset() { *x = For{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[17] + mi := &file_ast_ast_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1494,7 +1497,7 @@ func (x *For) String() string { func (*For) ProtoMessage() {} func (x *For) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[17] + mi := &file_ast_ast_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1507,7 +1510,7 @@ func (x *For) ProtoReflect() protoreflect.Message { // Deprecated: Use For.ProtoReflect.Descriptor instead. func (*For) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{17} + return file_ast_ast_proto_rawDescGZIP(), []int{17} } func (x *For) GetTarget() *Node { @@ -1545,7 +1548,7 @@ type FunctionDef struct { func (x *FunctionDef) Reset() { *x = FunctionDef{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[18] + mi := &file_ast_ast_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1558,7 +1561,7 @@ func (x *FunctionDef) String() string { func (*FunctionDef) ProtoMessage() {} func (x *FunctionDef) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[18] + mi := &file_ast_ast_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1571,7 +1574,7 @@ func (x *FunctionDef) ProtoReflect() protoreflect.Message { // Deprecated: Use FunctionDef.ProtoReflect.Descriptor instead. func (*FunctionDef) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{18} + return file_ast_ast_proto_rawDescGZIP(), []int{18} } func (x *FunctionDef) GetName() string { @@ -1615,7 +1618,7 @@ type If struct { func (x *If) Reset() { *x = If{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[19] + mi := &file_ast_ast_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1628,7 +1631,7 @@ func (x *If) String() string { func (*If) ProtoMessage() {} func (x *If) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[19] + mi := &file_ast_ast_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1641,7 +1644,7 @@ func (x *If) ProtoReflect() protoreflect.Message { // Deprecated: Use If.ProtoReflect.Descriptor instead. func (*If) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{19} + return file_ast_ast_proto_rawDescGZIP(), []int{19} } func (x *If) GetTest() *Node { @@ -1676,7 +1679,7 @@ type Import struct { func (x *Import) Reset() { *x = Import{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[20] + mi := &file_ast_ast_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1689,7 +1692,7 @@ func (x *Import) String() string { func (*Import) ProtoMessage() {} func (x *Import) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[20] + mi := &file_ast_ast_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1702,7 +1705,7 @@ func (x *Import) ProtoReflect() protoreflect.Message { // Deprecated: Use Import.ProtoReflect.Descriptor instead. func (*Import) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{20} + return file_ast_ast_proto_rawDescGZIP(), []int{20} } func (x *Import) GetNames() []*Node { @@ -1725,7 +1728,7 @@ type ImportFrom struct { func (x *ImportFrom) Reset() { *x = ImportFrom{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[21] + mi := &file_ast_ast_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1738,7 +1741,7 @@ func (x *ImportFrom) String() string { func (*ImportFrom) ProtoMessage() {} func (x *ImportFrom) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[21] + mi := &file_ast_ast_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1751,7 +1754,7 @@ func (x *ImportFrom) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportFrom.ProtoReflect.Descriptor instead. func (*ImportFrom) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{21} + return file_ast_ast_proto_rawDescGZIP(), []int{21} } func (x *ImportFrom) GetModule() string { @@ -1780,9 +1783,9 @@ func (x *ImportFrom) GetLevel() int32 { // // Imports should be grouped in the following order: // -// Standard library imports. -// Related third party imports. -// Local application/library specific imports. +// Standard library imports. +// Related third party imports. +// Local application/library specific imports. // // You should put a blank line between each group of imports. // @@ -1798,7 +1801,7 @@ type ImportGroup struct { func (x *ImportGroup) Reset() { *x = ImportGroup{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[22] + mi := &file_ast_ast_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1811,7 +1814,7 @@ func (x *ImportGroup) String() string { func (*ImportGroup) ProtoMessage() {} func (x *ImportGroup) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[22] + mi := &file_ast_ast_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1824,7 +1827,7 @@ func (x *ImportGroup) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportGroup.ProtoReflect.Descriptor instead. func (*ImportGroup) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{22} + return file_ast_ast_proto_rawDescGZIP(), []int{22} } func (x *ImportGroup) GetImports() []*Node { @@ -1843,7 +1846,7 @@ type Is struct { func (x *Is) Reset() { *x = Is{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[23] + mi := &file_ast_ast_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1856,7 +1859,7 @@ func (x *Is) String() string { func (*Is) ProtoMessage() {} func (x *Is) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[23] + mi := &file_ast_ast_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1869,7 +1872,7 @@ func (x *Is) ProtoReflect() protoreflect.Message { // Deprecated: Use Is.ProtoReflect.Descriptor instead. func (*Is) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{23} + return file_ast_ast_proto_rawDescGZIP(), []int{23} } type Keyword struct { @@ -1884,7 +1887,7 @@ type Keyword struct { func (x *Keyword) Reset() { *x = Keyword{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[24] + mi := &file_ast_ast_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1897,7 +1900,7 @@ func (x *Keyword) String() string { func (*Keyword) ProtoMessage() {} func (x *Keyword) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[24] + mi := &file_ast_ast_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1910,7 +1913,7 @@ func (x *Keyword) ProtoReflect() protoreflect.Message { // Deprecated: Use Keyword.ProtoReflect.Descriptor instead. func (*Keyword) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{24} + return file_ast_ast_proto_rawDescGZIP(), []int{24} } func (x *Keyword) GetArg() string { @@ -1938,7 +1941,7 @@ type Module struct { func (x *Module) Reset() { *x = Module{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[25] + mi := &file_ast_ast_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1951,7 +1954,7 @@ func (x *Module) String() string { func (*Module) ProtoMessage() {} func (x *Module) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[25] + mi := &file_ast_ast_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1964,7 +1967,7 @@ func (x *Module) ProtoReflect() protoreflect.Message { // Deprecated: Use Module.ProtoReflect.Descriptor instead. func (*Module) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{25} + return file_ast_ast_proto_rawDescGZIP(), []int{25} } func (x *Module) GetBody() []*Node { @@ -1985,7 +1988,7 @@ type Name struct { func (x *Name) Reset() { *x = Name{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[26] + mi := &file_ast_ast_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1998,7 +2001,7 @@ func (x *Name) String() string { func (*Name) ProtoMessage() {} func (x *Name) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[26] + mi := &file_ast_ast_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2011,7 +2014,7 @@ func (x *Name) ProtoReflect() protoreflect.Message { // Deprecated: Use Name.ProtoReflect.Descriptor instead. func (*Name) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{26} + return file_ast_ast_proto_rawDescGZIP(), []int{26} } func (x *Name) GetId() string { @@ -2030,7 +2033,7 @@ type Pass struct { func (x *Pass) Reset() { *x = Pass{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[27] + mi := &file_ast_ast_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2043,7 +2046,7 @@ func (x *Pass) String() string { func (*Pass) ProtoMessage() {} func (x *Pass) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[27] + mi := &file_ast_ast_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2056,7 +2059,7 @@ func (x *Pass) ProtoReflect() protoreflect.Message { // Deprecated: Use Pass.ProtoReflect.Descriptor instead. func (*Pass) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{27} + return file_ast_ast_proto_rawDescGZIP(), []int{27} } type Return struct { @@ -2070,7 +2073,7 @@ type Return struct { func (x *Return) Reset() { *x = Return{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[28] + mi := &file_ast_ast_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2083,7 +2086,7 @@ func (x *Return) String() string { func (*Return) ProtoMessage() {} func (x *Return) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[28] + mi := &file_ast_ast_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2096,7 +2099,7 @@ func (x *Return) ProtoReflect() protoreflect.Message { // Deprecated: Use Return.ProtoReflect.Descriptor instead. func (*Return) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{28} + return file_ast_ast_proto_rawDescGZIP(), []int{28} } func (x *Return) GetValue() *Node { @@ -2118,7 +2121,7 @@ type Subscript struct { func (x *Subscript) Reset() { *x = Subscript{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[29] + mi := &file_ast_ast_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2131,7 +2134,7 @@ func (x *Subscript) String() string { func (*Subscript) ProtoMessage() {} func (x *Subscript) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[29] + mi := &file_ast_ast_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2144,7 +2147,7 @@ func (x *Subscript) ProtoReflect() protoreflect.Message { // Deprecated: Use Subscript.ProtoReflect.Descriptor instead. func (*Subscript) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{29} + return file_ast_ast_proto_rawDescGZIP(), []int{29} } func (x *Subscript) GetValue() *Name { @@ -2172,7 +2175,7 @@ type Yield struct { func (x *Yield) Reset() { *x = Yield{} if protoimpl.UnsafeEnabled { - mi := &file_python_ast_proto_msgTypes[30] + mi := &file_ast_ast_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2185,7 +2188,7 @@ func (x *Yield) String() string { func (*Yield) ProtoMessage() {} func (x *Yield) ProtoReflect() protoreflect.Message { - mi := &file_python_ast_proto_msgTypes[30] + mi := &file_ast_ast_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2198,7 +2201,7 @@ func (x *Yield) ProtoReflect() protoreflect.Message { // Deprecated: Use Yield.ProtoReflect.Descriptor instead. func (*Yield) Descriptor() ([]byte, []int) { - return file_python_ast_proto_rawDescGZIP(), []int{30} + return file_ast_ast_proto_rawDescGZIP(), []int{30} } func (x *Yield) GetValue() *Node { @@ -2208,394 +2211,364 @@ func (x *Yield) GetValue() *Node { return nil } -var File_python_ast_proto protoreflect.FileDescriptor - -var file_python_ast_proto_rawDesc = []byte{ - 0x0a, 0x10, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2f, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x0a, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x22, 0xb0, - 0x0b, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x63, 0x6c, 0x61, 0x73, 0x73, - 0x5f, 0x64, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x44, 0x65, 0x66, - 0x48, 0x00, 0x52, 0x08, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x44, 0x65, 0x66, 0x12, 0x2c, 0x0a, 0x06, - 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, - 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, - 0x48, 0x00, 0x52, 0x06, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6d, - 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x49, 0x6d, 0x70, - 0x6f, 0x72, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x48, 0x00, 0x52, 0x0a, 0x49, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x2c, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, - 0x73, 0x74, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x06, 0x4d, 0x6f, 0x64, - 0x75, 0x6c, 0x65, 0x12, 0x29, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, - 0x41, 0x6c, 0x69, 0x61, 0x73, 0x48, 0x00, 0x52, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x36, - 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x5f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, - 0x41, 0x6e, 0x6e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x48, 0x00, 0x52, 0x09, 0x41, 0x6e, 0x6e, - 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0x26, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, - 0x74, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x48, 0x00, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x35, - 0x0a, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x48, 0x00, 0x52, 0x09, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, - 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x48, - 0x00, 0x52, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x08, - 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, - 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x73, +var File_ast_ast_proto protoreflect.FileDescriptor + +var file_ast_ast_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x61, 0x73, 0x74, 0x2f, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x03, 0x61, 0x73, 0x74, 0x22, 0xde, 0x09, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, + 0x09, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x64, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x44, 0x65, 0x66, 0x48, + 0x00, 0x52, 0x08, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x44, 0x65, 0x66, 0x12, 0x25, 0x0a, 0x06, 0x69, + 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, 0x52, 0x06, 0x49, 0x6d, 0x70, 0x6f, + 0x72, 0x74, 0x12, 0x32, 0x0a, 0x0b, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x66, 0x72, 0x6f, + 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x49, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x48, 0x00, 0x52, 0x0a, 0x49, 0x6d, 0x70, 0x6f, + 0x72, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x25, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4d, 0x6f, 0x64, + 0x75, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x06, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x22, 0x0a, + 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x61, + 0x73, 0x74, 0x2e, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x48, 0x00, 0x52, 0x05, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x12, 0x2f, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x5f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x6e, 0x6e, 0x41, + 0x73, 0x73, 0x69, 0x67, 0x6e, 0x48, 0x00, 0x52, 0x09, 0x41, 0x6e, 0x6e, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x12, 0x1f, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x48, 0x00, 0x52, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x53, 0x75, 0x62, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x48, 0x00, 0x52, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x12, 0x2e, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x48, 0x00, 0x52, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x08, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, - 0x12, 0x2c, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x73, - 0x73, 0x69, 0x67, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0x2f, - 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6d, - 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x26, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x48, - 0x00, 0x52, 0x04, 0x45, 0x78, 0x70, 0x72, 0x12, 0x26, 0x0a, 0x04, 0x63, 0x61, 0x6c, 0x6c, 0x18, - 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, - 0x73, 0x74, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x48, 0x00, 0x52, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, - 0x3c, 0x0a, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x18, - 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, - 0x73, 0x74, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x48, 0x00, - 0x52, 0x0b, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x12, 0x23, 0x0a, - 0x03, 0x61, 0x72, 0x67, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x72, 0x67, 0x48, 0x00, 0x52, 0x03, 0x41, - 0x72, 0x67, 0x12, 0x35, 0x0a, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, - 0x73, 0x74, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x48, 0x00, 0x52, 0x09, - 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4c, 0x0a, 0x12, 0x61, 0x73, 0x79, - 0x6e, 0x63, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x18, - 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, - 0x73, 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x44, 0x65, 0x66, 0x48, 0x00, 0x52, 0x10, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x12, 0x26, 0x0a, 0x04, 0x70, 0x61, 0x73, 0x73, 0x18, - 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, - 0x73, 0x74, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x48, 0x00, 0x52, 0x04, 0x50, 0x61, 0x73, 0x73, 0x12, - 0x26, 0x0a, 0x04, 0x64, 0x69, 0x63, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x44, 0x69, 0x63, 0x74, 0x48, - 0x00, 0x52, 0x04, 0x44, 0x69, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x02, 0x69, 0x66, 0x18, 0x15, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, - 0x2e, 0x49, 0x66, 0x48, 0x00, 0x52, 0x02, 0x49, 0x66, 0x12, 0x2f, 0x0a, 0x07, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x72, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x48, - 0x00, 0x52, 0x07, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x48, 0x00, - 0x52, 0x06, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x12, 0x20, 0x0a, 0x02, 0x69, 0x73, 0x18, 0x18, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, - 0x74, 0x2e, 0x49, 0x73, 0x48, 0x00, 0x52, 0x02, 0x49, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x6b, 0x65, - 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x79, - 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, - 0x48, 0x00, 0x52, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x29, 0x0a, 0x05, 0x79, - 0x69, 0x65, 0x6c, 0x64, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x59, 0x69, 0x65, 0x6c, 0x64, 0x48, 0x00, 0x52, - 0x05, 0x59, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x23, 0x0a, 0x03, 0x66, 0x6f, 0x72, 0x18, 0x1b, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, - 0x2e, 0x46, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x03, 0x46, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x05, 0x61, - 0x77, 0x61, 0x69, 0x74, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x77, 0x61, 0x69, 0x74, 0x48, 0x00, 0x52, - 0x05, 0x41, 0x77, 0x61, 0x69, 0x74, 0x12, 0x33, 0x0a, 0x09, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x5f, - 0x66, 0x6f, 0x72, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x79, 0x74, 0x68, - 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x6f, 0x72, 0x48, - 0x00, 0x52, 0x08, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x6f, 0x72, 0x12, 0x3c, 0x0a, 0x0c, 0x69, - 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x1e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x49, - 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x0b, 0x49, 0x6d, - 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x06, 0x0a, 0x04, 0x6e, 0x6f, 0x64, - 0x65, 0x22, 0x1b, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2f, - 0x0a, 0x05, 0x41, 0x77, 0x61, 0x69, 0x74, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, - 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0x47, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x26, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, - 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x74, 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x61, 0x74, 0x74, 0x72, 0x22, 0x99, 0x01, 0x0a, 0x09, 0x41, 0x6e, 0x6e, - 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0x28, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, - 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x12, 0x30, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, - 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x06, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x6f, - 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, - 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x49, 0x0a, 0x03, 0x41, 0x72, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x61, - 0x72, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, 0x67, 0x12, 0x30, 0x0a, - 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x63, 0x0a, 0x09, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x04, - 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x72, 0x67, 0x52, 0x04, 0x61, 0x72, 0x67, - 0x73, 0x12, 0x31, 0x0a, 0x0c, 0x6b, 0x77, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x61, 0x72, 0x67, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, - 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x72, 0x67, 0x52, 0x0a, 0x6b, 0x77, 0x6f, 0x6e, 0x6c, 0x79, - 0x61, 0x72, 0x67, 0x73, 0x22, 0x80, 0x01, 0x0a, 0x08, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x6f, - 0x72, 0x12, 0x28, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x69, - 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, - 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, - 0x72, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xa3, 0x01, 0x0a, 0x10, 0x41, 0x73, 0x79, 0x6e, - 0x63, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, + 0x12, 0x25, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0b, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x48, 0x00, 0x52, + 0x06, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x74, 0x12, 0x1f, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x48, 0x00, 0x52, 0x04, 0x45, 0x78, + 0x70, 0x72, 0x12, 0x1f, 0x0a, 0x04, 0x63, 0x61, 0x6c, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x48, 0x00, 0x52, 0x04, 0x43, + 0x61, 0x6c, 0x6c, 0x12, 0x35, 0x0a, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x64, 0x65, 0x66, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x48, 0x00, 0x52, 0x0b, 0x46, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x12, 0x1c, 0x0a, 0x03, 0x61, 0x72, + 0x67, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x72, + 0x67, 0x48, 0x00, 0x52, 0x03, 0x41, 0x72, 0x67, 0x12, 0x2e, 0x0a, 0x09, 0x61, 0x72, 0x67, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x48, 0x00, 0x52, 0x09, 0x41, + 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x12, 0x61, 0x73, 0x79, 0x6e, + 0x63, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x18, 0x12, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, + 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x48, 0x00, 0x52, 0x10, 0x41, + 0x73, 0x79, 0x6e, 0x63, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x12, + 0x1f, 0x0a, 0x04, 0x70, 0x61, 0x73, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, + 0x61, 0x73, 0x74, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x48, 0x00, 0x52, 0x04, 0x50, 0x61, 0x73, 0x73, + 0x12, 0x1f, 0x0a, 0x04, 0x64, 0x69, 0x63, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, + 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x44, 0x69, 0x63, 0x74, 0x48, 0x00, 0x52, 0x04, 0x44, 0x69, 0x63, + 0x74, 0x12, 0x19, 0x0a, 0x02, 0x69, 0x66, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x07, 0x2e, + 0x61, 0x73, 0x74, 0x2e, 0x49, 0x66, 0x48, 0x00, 0x52, 0x02, 0x49, 0x66, 0x12, 0x28, 0x0a, 0x07, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x61, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x48, 0x00, 0x52, 0x07, 0x43, + 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x12, 0x19, 0x0a, + 0x02, 0x69, 0x73, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x49, 0x73, 0x48, 0x00, 0x52, 0x02, 0x49, 0x73, 0x12, 0x28, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, + 0x6f, 0x72, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x00, 0x52, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, + 0x72, 0x64, 0x12, 0x22, 0x0a, 0x05, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x1a, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0a, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x59, 0x69, 0x65, 0x6c, 0x64, 0x48, 0x00, 0x52, + 0x05, 0x59, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1c, 0x0a, 0x03, 0x66, 0x6f, 0x72, 0x18, 0x1b, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x46, 0x6f, 0x72, 0x48, 0x00, 0x52, + 0x03, 0x46, 0x6f, 0x72, 0x12, 0x22, 0x0a, 0x05, 0x61, 0x77, 0x61, 0x69, 0x74, 0x18, 0x1c, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x77, 0x61, 0x69, 0x74, 0x48, + 0x00, 0x52, 0x05, 0x41, 0x77, 0x61, 0x69, 0x74, 0x12, 0x2c, 0x0a, 0x09, 0x61, 0x73, 0x79, 0x6e, + 0x63, 0x5f, 0x66, 0x6f, 0x72, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x08, 0x41, 0x73, + 0x79, 0x6e, 0x63, 0x46, 0x6f, 0x72, 0x12, 0x35, 0x0a, 0x0c, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, + 0x73, 0x74, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, + 0x52, 0x0b, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x06, 0x0a, + 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x1b, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x22, 0x28, 0x0a, 0x05, 0x41, 0x77, 0x61, 0x69, 0x74, 0x12, 0x1f, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x40, 0x0a, 0x09, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x74, + 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x74, 0x74, 0x72, 0x22, 0x8b, + 0x01, 0x0a, 0x09, 0x41, 0x6e, 0x6e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0x21, 0x0a, 0x06, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, + 0x73, 0x74, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, + 0x29, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x0a, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, + 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x42, 0x0a, 0x03, + 0x41, 0x72, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x72, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x61, 0x72, 0x67, 0x12, 0x29, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x55, 0x0a, 0x09, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x0a, + 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x41, 0x72, 0x67, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x2a, 0x0a, 0x0c, 0x6b, + 0x77, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x08, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x72, 0x67, 0x52, 0x0a, 0x6b, 0x77, 0x6f, + 0x6e, 0x6c, 0x79, 0x61, 0x72, 0x67, 0x73, 0x22, 0x6b, 0x0a, 0x08, 0x41, 0x73, 0x79, 0x6e, 0x63, + 0x46, 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x06, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x1d, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x04, 0x69, 0x74, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x75, + 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, + 0x04, 0x41, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x04, 0x61, 0x72, 0x67, + 0x73, 0x12, 0x1d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x23, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x73, 0x22, 0x68, 0x0a, 0x06, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, + 0x23, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, + 0x6e, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x1d, 0x0a, 0x04, 0x66, 0x75, 0x6e, 0x63, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x04, 0x66, 0x75, 0x6e, 0x63, 0x12, 0x1d, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x28, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4b, 0x65, + 0x79, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x22, + 0xb8, 0x01, 0x0a, 0x08, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x44, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x29, 0x0a, 0x04, 0x41, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x72, 0x67, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x24, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, - 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x2a, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x22, 0x76, 0x0a, - 0x06, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0x2a, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, - 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, - 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, - 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x83, 0x01, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x24, - 0x0a, 0x04, 0x66, 0x75, 0x6e, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, - 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, - 0x66, 0x75, 0x6e, 0x63, 0x12, 0x24, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x2f, 0x0a, 0x08, 0x6b, 0x65, - 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, - 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, - 0x64, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x08, - 0x43, 0x6c, 0x61, 0x73, 0x73, 0x44, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x05, - 0x62, 0x61, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, - 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x62, - 0x61, 0x73, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, - 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, - 0x64, 0x73, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x38, 0x0a, 0x0e, 0x64, 0x65, 0x63, 0x6f, - 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x52, 0x0e, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6c, 0x69, - 0x73, 0x74, 0x22, 0x1d, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, - 0x74, 0x22, 0x87, 0x01, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x12, 0x24, 0x0a, - 0x04, 0x6c, 0x65, 0x66, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, - 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6c, - 0x65, 0x66, 0x74, 0x12, 0x22, 0x0a, 0x03, 0x6f, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x52, 0x03, 0x6f, 0x70, 0x73, 0x12, 0x32, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, - 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x0b, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x54, 0x0a, 0x08, 0x43, - 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x12, 0x15, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x12, - 0x0a, 0x03, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x03, 0x69, - 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x48, 0x00, 0x52, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x22, 0x56, 0x0a, 0x04, 0x44, 0x69, 0x63, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x6b, 0x65, 0x79, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, - 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x12, - 0x28, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x2e, 0x0a, 0x04, 0x45, 0x78, 0x70, - 0x72, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x7b, 0x0a, 0x03, 0x46, 0x6f, 0x72, - 0x12, 0x28, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x69, 0x74, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, - 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x72, - 0x12, 0x24, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x9e, 0x01, 0x0a, 0x0b, 0x46, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x04, 0x41, 0x72, - 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, - 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, - 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x07, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, - 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x22, 0x7b, 0x0a, 0x02, 0x49, 0x66, 0x12, 0x24, 0x0a, - 0x04, 0x74, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, - 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x74, - 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x29, 0x0a, 0x07, 0x6f, 0x72, 0x5f, - 0x65, 0x6c, 0x73, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x6f, 0x72, - 0x65, 0x6c, 0x73, 0x65, 0x22, 0x30, 0x0a, 0x06, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x26, - 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, - 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x62, 0x0a, 0x0a, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, - 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x26, 0x0a, 0x05, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, - 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, + 0x12, 0x1f, 0x0a, 0x05, 0x62, 0x61, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x62, 0x61, 0x73, 0x65, + 0x73, 0x12, 0x25, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x08, + 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x31, 0x0a, 0x0e, 0x64, 0x65, 0x63, 0x6f, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x0e, 0x64, 0x65, 0x63, 0x6f, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x1d, 0x0a, 0x07, 0x43, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x22, 0x72, 0x0a, 0x07, 0x43, 0x6f, 0x6d, + 0x70, 0x61, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x04, 0x6c, 0x65, 0x66, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6c, + 0x65, 0x66, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x6f, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x03, 0x6f, 0x70, 0x73, + 0x12, 0x2b, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x54, 0x0a, + 0x08, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x12, 0x15, 0x0a, 0x03, 0x73, 0x74, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x12, 0x12, 0x0a, 0x03, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, + 0x03, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x22, 0x48, 0x0a, 0x04, 0x44, 0x69, 0x63, 0x74, 0x12, 0x1d, 0x0a, 0x04, 0x6b, + 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x21, 0x0a, 0x06, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x27, 0x0a, + 0x04, 0x45, 0x78, 0x70, 0x72, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x66, 0x0a, 0x03, 0x46, 0x6f, 0x72, 0x12, 0x21, 0x0a, + 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, + 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x12, 0x1d, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, + 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x72, 0x12, + 0x1d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, + 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x89, + 0x01, 0x0a, 0x0b, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x04, 0x41, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x23, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x07, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x22, 0x66, 0x0a, 0x02, 0x49, 0x66, + 0x12, 0x1d, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, + 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, + 0x1d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, + 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x22, + 0x0a, 0x07, 0x6f, 0x72, 0x5f, 0x65, 0x6c, 0x73, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x6f, 0x72, 0x65, 0x6c, + 0x73, 0x65, 0x22, 0x29, 0x0a, 0x06, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1f, 0x0a, 0x05, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x5b, 0x0a, + 0x0a, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x16, 0x0a, 0x06, 0x6d, + 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x64, + 0x75, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x39, 0x0a, 0x0b, 0x49, 0x6d, - 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2a, 0x0a, 0x07, 0x69, 0x6d, 0x70, - 0x6f, 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x69, 0x6d, - 0x70, 0x6f, 0x72, 0x74, 0x73, 0x22, 0x04, 0x0a, 0x02, 0x49, 0x73, 0x22, 0x43, 0x0a, 0x07, 0x4b, - 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x72, 0x67, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, 0x67, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, - 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x2e, 0x0a, 0x06, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, - 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x22, 0x16, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x06, 0x0a, 0x04, 0x50, 0x61, 0x73, 0x73, - 0x22, 0x30, 0x0a, 0x06, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, - 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x5b, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, - 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x61, 0x6d, 0x65, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x6c, 0x69, 0x63, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, - 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x22, - 0x2f, 0x0a, 0x05, 0x59, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, - 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, - 0x79, 0x6c, 0x65, 0x63, 0x6f, 0x6e, 0x72, 0x6f, 0x79, 0x2f, 0x73, 0x71, 0x6c, 0x63, 0x2f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2f, 0x61, + 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x32, 0x0a, 0x0b, 0x49, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x23, 0x0a, 0x07, 0x69, 0x6d, 0x70, + 0x6f, 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x22, 0x04, + 0x0a, 0x02, 0x49, 0x73, 0x22, 0x3c, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, + 0x10, 0x0a, 0x03, 0x61, 0x72, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, + 0x67, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x27, 0x0a, 0x06, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x16, 0x0a, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x22, 0x06, 0x0a, 0x04, 0x50, 0x61, 0x73, 0x73, 0x22, 0x29, 0x0a, 0x06, 0x52, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x05, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, + 0x73, 0x6c, 0x69, 0x63, 0x65, 0x22, 0x28, 0x0a, 0x05, 0x59, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1f, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, + 0x61, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, + 0x71, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x73, 0x74, 0x42, 0x08, 0x41, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x73, 0x71, 0x6c, 0x63, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x73, 0x71, 0x6c, 0x63, + 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x73, 0x74, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, + 0x03, 0x41, 0x73, 0x74, 0xca, 0x02, 0x03, 0x41, 0x73, 0x74, 0xe2, 0x02, 0x0f, 0x41, 0x73, 0x74, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x03, 0x41, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_python_ast_proto_rawDescOnce sync.Once - file_python_ast_proto_rawDescData = file_python_ast_proto_rawDesc + file_ast_ast_proto_rawDescOnce sync.Once + file_ast_ast_proto_rawDescData = file_ast_ast_proto_rawDesc ) -func file_python_ast_proto_rawDescGZIP() []byte { - file_python_ast_proto_rawDescOnce.Do(func() { - file_python_ast_proto_rawDescData = protoimpl.X.CompressGZIP(file_python_ast_proto_rawDescData) +func file_ast_ast_proto_rawDescGZIP() []byte { + file_ast_ast_proto_rawDescOnce.Do(func() { + file_ast_ast_proto_rawDescData = protoimpl.X.CompressGZIP(file_ast_ast_proto_rawDescData) }) - return file_python_ast_proto_rawDescData -} - -var file_python_ast_proto_msgTypes = make([]protoimpl.MessageInfo, 31) -var file_python_ast_proto_goTypes = []interface{}{ - (*Node)(nil), // 0: python.ast.Node - (*Alias)(nil), // 1: python.ast.Alias - (*Await)(nil), // 2: python.ast.Await - (*Attribute)(nil), // 3: python.ast.Attribute - (*AnnAssign)(nil), // 4: python.ast.AnnAssign - (*Arg)(nil), // 5: python.ast.Arg - (*Arguments)(nil), // 6: python.ast.Arguments - (*AsyncFor)(nil), // 7: python.ast.AsyncFor - (*AsyncFunctionDef)(nil), // 8: python.ast.AsyncFunctionDef - (*Assign)(nil), // 9: python.ast.Assign - (*Call)(nil), // 10: python.ast.Call - (*ClassDef)(nil), // 11: python.ast.ClassDef - (*Comment)(nil), // 12: python.ast.Comment - (*Compare)(nil), // 13: python.ast.Compare - (*Constant)(nil), // 14: python.ast.Constant - (*Dict)(nil), // 15: python.ast.Dict - (*Expr)(nil), // 16: python.ast.Expr - (*For)(nil), // 17: python.ast.For - (*FunctionDef)(nil), // 18: python.ast.FunctionDef - (*If)(nil), // 19: python.ast.If - (*Import)(nil), // 20: python.ast.Import - (*ImportFrom)(nil), // 21: python.ast.ImportFrom - (*ImportGroup)(nil), // 22: python.ast.ImportGroup - (*Is)(nil), // 23: python.ast.Is - (*Keyword)(nil), // 24: python.ast.Keyword - (*Module)(nil), // 25: python.ast.Module - (*Name)(nil), // 26: python.ast.Name - (*Pass)(nil), // 27: python.ast.Pass - (*Return)(nil), // 28: python.ast.Return - (*Subscript)(nil), // 29: python.ast.Subscript - (*Yield)(nil), // 30: python.ast.Yield -} -var file_python_ast_proto_depIdxs = []int32{ - 11, // 0: python.ast.Node.class_def:type_name -> python.ast.ClassDef - 20, // 1: python.ast.Node.import:type_name -> python.ast.Import - 21, // 2: python.ast.Node.import_from:type_name -> python.ast.ImportFrom - 25, // 3: python.ast.Node.module:type_name -> python.ast.Module - 1, // 4: python.ast.Node.alias:type_name -> python.ast.Alias - 4, // 5: python.ast.Node.ann_assign:type_name -> python.ast.AnnAssign - 26, // 6: python.ast.Node.name:type_name -> python.ast.Name - 29, // 7: python.ast.Node.subscript:type_name -> python.ast.Subscript - 3, // 8: python.ast.Node.attribute:type_name -> python.ast.Attribute - 14, // 9: python.ast.Node.constant:type_name -> python.ast.Constant - 9, // 10: python.ast.Node.assign:type_name -> python.ast.Assign - 12, // 11: python.ast.Node.comment:type_name -> python.ast.Comment - 16, // 12: python.ast.Node.expr:type_name -> python.ast.Expr - 10, // 13: python.ast.Node.call:type_name -> python.ast.Call - 18, // 14: python.ast.Node.function_def:type_name -> python.ast.FunctionDef - 5, // 15: python.ast.Node.arg:type_name -> python.ast.Arg - 6, // 16: python.ast.Node.arguments:type_name -> python.ast.Arguments - 8, // 17: python.ast.Node.async_function_def:type_name -> python.ast.AsyncFunctionDef - 27, // 18: python.ast.Node.pass:type_name -> python.ast.Pass - 15, // 19: python.ast.Node.dict:type_name -> python.ast.Dict - 19, // 20: python.ast.Node.if:type_name -> python.ast.If - 13, // 21: python.ast.Node.compare:type_name -> python.ast.Compare - 28, // 22: python.ast.Node.return:type_name -> python.ast.Return - 23, // 23: python.ast.Node.is:type_name -> python.ast.Is - 24, // 24: python.ast.Node.keyword:type_name -> python.ast.Keyword - 30, // 25: python.ast.Node.yield:type_name -> python.ast.Yield - 17, // 26: python.ast.Node.for:type_name -> python.ast.For - 2, // 27: python.ast.Node.await:type_name -> python.ast.Await - 7, // 28: python.ast.Node.async_for:type_name -> python.ast.AsyncFor - 22, // 29: python.ast.Node.import_group:type_name -> python.ast.ImportGroup - 0, // 30: python.ast.Await.value:type_name -> python.ast.Node - 0, // 31: python.ast.Attribute.value:type_name -> python.ast.Node - 26, // 32: python.ast.AnnAssign.target:type_name -> python.ast.Name - 0, // 33: python.ast.AnnAssign.annotation:type_name -> python.ast.Node - 0, // 34: python.ast.Arg.annotation:type_name -> python.ast.Node - 5, // 35: python.ast.Arguments.args:type_name -> python.ast.Arg - 5, // 36: python.ast.Arguments.kw_only_args:type_name -> python.ast.Arg - 0, // 37: python.ast.AsyncFor.target:type_name -> python.ast.Node - 0, // 38: python.ast.AsyncFor.iter:type_name -> python.ast.Node - 0, // 39: python.ast.AsyncFor.body:type_name -> python.ast.Node - 6, // 40: python.ast.AsyncFunctionDef.Args:type_name -> python.ast.Arguments - 0, // 41: python.ast.AsyncFunctionDef.body:type_name -> python.ast.Node - 0, // 42: python.ast.AsyncFunctionDef.returns:type_name -> python.ast.Node - 0, // 43: python.ast.Assign.targets:type_name -> python.ast.Node - 0, // 44: python.ast.Assign.value:type_name -> python.ast.Node - 0, // 45: python.ast.Call.func:type_name -> python.ast.Node - 0, // 46: python.ast.Call.args:type_name -> python.ast.Node - 24, // 47: python.ast.Call.keywords:type_name -> python.ast.Keyword - 0, // 48: python.ast.ClassDef.bases:type_name -> python.ast.Node - 0, // 49: python.ast.ClassDef.keywords:type_name -> python.ast.Node - 0, // 50: python.ast.ClassDef.body:type_name -> python.ast.Node - 0, // 51: python.ast.ClassDef.decorator_list:type_name -> python.ast.Node - 0, // 52: python.ast.Compare.left:type_name -> python.ast.Node - 0, // 53: python.ast.Compare.ops:type_name -> python.ast.Node - 0, // 54: python.ast.Compare.comparators:type_name -> python.ast.Node - 0, // 55: python.ast.Dict.keys:type_name -> python.ast.Node - 0, // 56: python.ast.Dict.values:type_name -> python.ast.Node - 0, // 57: python.ast.Expr.value:type_name -> python.ast.Node - 0, // 58: python.ast.For.target:type_name -> python.ast.Node - 0, // 59: python.ast.For.iter:type_name -> python.ast.Node - 0, // 60: python.ast.For.body:type_name -> python.ast.Node - 6, // 61: python.ast.FunctionDef.Args:type_name -> python.ast.Arguments - 0, // 62: python.ast.FunctionDef.body:type_name -> python.ast.Node - 0, // 63: python.ast.FunctionDef.returns:type_name -> python.ast.Node - 0, // 64: python.ast.If.test:type_name -> python.ast.Node - 0, // 65: python.ast.If.body:type_name -> python.ast.Node - 0, // 66: python.ast.If.or_else:type_name -> python.ast.Node - 0, // 67: python.ast.Import.names:type_name -> python.ast.Node - 0, // 68: python.ast.ImportFrom.names:type_name -> python.ast.Node - 0, // 69: python.ast.ImportGroup.imports:type_name -> python.ast.Node - 0, // 70: python.ast.Keyword.value:type_name -> python.ast.Node - 0, // 71: python.ast.Module.body:type_name -> python.ast.Node - 0, // 72: python.ast.Return.value:type_name -> python.ast.Node - 26, // 73: python.ast.Subscript.value:type_name -> python.ast.Name - 0, // 74: python.ast.Subscript.slice:type_name -> python.ast.Node - 0, // 75: python.ast.Yield.value:type_name -> python.ast.Node + return file_ast_ast_proto_rawDescData +} + +var file_ast_ast_proto_msgTypes = make([]protoimpl.MessageInfo, 31) +var file_ast_ast_proto_goTypes = []interface{}{ + (*Node)(nil), // 0: ast.Node + (*Alias)(nil), // 1: ast.Alias + (*Await)(nil), // 2: ast.Await + (*Attribute)(nil), // 3: ast.Attribute + (*AnnAssign)(nil), // 4: ast.AnnAssign + (*Arg)(nil), // 5: ast.Arg + (*Arguments)(nil), // 6: ast.Arguments + (*AsyncFor)(nil), // 7: ast.AsyncFor + (*AsyncFunctionDef)(nil), // 8: ast.AsyncFunctionDef + (*Assign)(nil), // 9: ast.Assign + (*Call)(nil), // 10: ast.Call + (*ClassDef)(nil), // 11: ast.ClassDef + (*Comment)(nil), // 12: ast.Comment + (*Compare)(nil), // 13: ast.Compare + (*Constant)(nil), // 14: ast.Constant + (*Dict)(nil), // 15: ast.Dict + (*Expr)(nil), // 16: ast.Expr + (*For)(nil), // 17: ast.For + (*FunctionDef)(nil), // 18: ast.FunctionDef + (*If)(nil), // 19: ast.If + (*Import)(nil), // 20: ast.Import + (*ImportFrom)(nil), // 21: ast.ImportFrom + (*ImportGroup)(nil), // 22: ast.ImportGroup + (*Is)(nil), // 23: ast.Is + (*Keyword)(nil), // 24: ast.Keyword + (*Module)(nil), // 25: ast.Module + (*Name)(nil), // 26: ast.Name + (*Pass)(nil), // 27: ast.Pass + (*Return)(nil), // 28: ast.Return + (*Subscript)(nil), // 29: ast.Subscript + (*Yield)(nil), // 30: ast.Yield +} +var file_ast_ast_proto_depIdxs = []int32{ + 11, // 0: ast.Node.class_def:type_name -> ast.ClassDef + 20, // 1: ast.Node.import:type_name -> ast.Import + 21, // 2: ast.Node.import_from:type_name -> ast.ImportFrom + 25, // 3: ast.Node.module:type_name -> ast.Module + 1, // 4: ast.Node.alias:type_name -> ast.Alias + 4, // 5: ast.Node.ann_assign:type_name -> ast.AnnAssign + 26, // 6: ast.Node.name:type_name -> ast.Name + 29, // 7: ast.Node.subscript:type_name -> ast.Subscript + 3, // 8: ast.Node.attribute:type_name -> ast.Attribute + 14, // 9: ast.Node.constant:type_name -> ast.Constant + 9, // 10: ast.Node.assign:type_name -> ast.Assign + 12, // 11: ast.Node.comment:type_name -> ast.Comment + 16, // 12: ast.Node.expr:type_name -> ast.Expr + 10, // 13: ast.Node.call:type_name -> ast.Call + 18, // 14: ast.Node.function_def:type_name -> ast.FunctionDef + 5, // 15: ast.Node.arg:type_name -> ast.Arg + 6, // 16: ast.Node.arguments:type_name -> ast.Arguments + 8, // 17: ast.Node.async_function_def:type_name -> ast.AsyncFunctionDef + 27, // 18: ast.Node.pass:type_name -> ast.Pass + 15, // 19: ast.Node.dict:type_name -> ast.Dict + 19, // 20: ast.Node.if:type_name -> ast.If + 13, // 21: ast.Node.compare:type_name -> ast.Compare + 28, // 22: ast.Node.return:type_name -> ast.Return + 23, // 23: ast.Node.is:type_name -> ast.Is + 24, // 24: ast.Node.keyword:type_name -> ast.Keyword + 30, // 25: ast.Node.yield:type_name -> ast.Yield + 17, // 26: ast.Node.for:type_name -> ast.For + 2, // 27: ast.Node.await:type_name -> ast.Await + 7, // 28: ast.Node.async_for:type_name -> ast.AsyncFor + 22, // 29: ast.Node.import_group:type_name -> ast.ImportGroup + 0, // 30: ast.Await.value:type_name -> ast.Node + 0, // 31: ast.Attribute.value:type_name -> ast.Node + 26, // 32: ast.AnnAssign.target:type_name -> ast.Name + 0, // 33: ast.AnnAssign.annotation:type_name -> ast.Node + 0, // 34: ast.Arg.annotation:type_name -> ast.Node + 5, // 35: ast.Arguments.args:type_name -> ast.Arg + 5, // 36: ast.Arguments.kw_only_args:type_name -> ast.Arg + 0, // 37: ast.AsyncFor.target:type_name -> ast.Node + 0, // 38: ast.AsyncFor.iter:type_name -> ast.Node + 0, // 39: ast.AsyncFor.body:type_name -> ast.Node + 6, // 40: ast.AsyncFunctionDef.Args:type_name -> ast.Arguments + 0, // 41: ast.AsyncFunctionDef.body:type_name -> ast.Node + 0, // 42: ast.AsyncFunctionDef.returns:type_name -> ast.Node + 0, // 43: ast.Assign.targets:type_name -> ast.Node + 0, // 44: ast.Assign.value:type_name -> ast.Node + 0, // 45: ast.Call.func:type_name -> ast.Node + 0, // 46: ast.Call.args:type_name -> ast.Node + 24, // 47: ast.Call.keywords:type_name -> ast.Keyword + 0, // 48: ast.ClassDef.bases:type_name -> ast.Node + 0, // 49: ast.ClassDef.keywords:type_name -> ast.Node + 0, // 50: ast.ClassDef.body:type_name -> ast.Node + 0, // 51: ast.ClassDef.decorator_list:type_name -> ast.Node + 0, // 52: ast.Compare.left:type_name -> ast.Node + 0, // 53: ast.Compare.ops:type_name -> ast.Node + 0, // 54: ast.Compare.comparators:type_name -> ast.Node + 0, // 55: ast.Dict.keys:type_name -> ast.Node + 0, // 56: ast.Dict.values:type_name -> ast.Node + 0, // 57: ast.Expr.value:type_name -> ast.Node + 0, // 58: ast.For.target:type_name -> ast.Node + 0, // 59: ast.For.iter:type_name -> ast.Node + 0, // 60: ast.For.body:type_name -> ast.Node + 6, // 61: ast.FunctionDef.Args:type_name -> ast.Arguments + 0, // 62: ast.FunctionDef.body:type_name -> ast.Node + 0, // 63: ast.FunctionDef.returns:type_name -> ast.Node + 0, // 64: ast.If.test:type_name -> ast.Node + 0, // 65: ast.If.body:type_name -> ast.Node + 0, // 66: ast.If.or_else:type_name -> ast.Node + 0, // 67: ast.Import.names:type_name -> ast.Node + 0, // 68: ast.ImportFrom.names:type_name -> ast.Node + 0, // 69: ast.ImportGroup.imports:type_name -> ast.Node + 0, // 70: ast.Keyword.value:type_name -> ast.Node + 0, // 71: ast.Module.body:type_name -> ast.Node + 0, // 72: ast.Return.value:type_name -> ast.Node + 26, // 73: ast.Subscript.value:type_name -> ast.Name + 0, // 74: ast.Subscript.slice:type_name -> ast.Node + 0, // 75: ast.Yield.value:type_name -> ast.Node 76, // [76:76] is the sub-list for method output_type 76, // [76:76] is the sub-list for method input_type 76, // [76:76] is the sub-list for extension type_name @@ -2603,13 +2576,13 @@ var file_python_ast_proto_depIdxs = []int32{ 0, // [0:76] is the sub-list for field type_name } -func init() { file_python_ast_proto_init() } -func file_python_ast_proto_init() { - if File_python_ast_proto != nil { +func init() { file_ast_ast_proto_init() } +func file_ast_ast_proto_init() { + if File_ast_ast_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_python_ast_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Node); i { case 0: return &v.state @@ -2621,7 +2594,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Alias); i { case 0: return &v.state @@ -2633,7 +2606,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Await); i { case 0: return &v.state @@ -2645,7 +2618,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Attribute); i { case 0: return &v.state @@ -2657,7 +2630,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AnnAssign); i { case 0: return &v.state @@ -2669,7 +2642,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Arg); i { case 0: return &v.state @@ -2681,7 +2654,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Arguments); i { case 0: return &v.state @@ -2693,7 +2666,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AsyncFor); i { case 0: return &v.state @@ -2705,7 +2678,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AsyncFunctionDef); i { case 0: return &v.state @@ -2717,7 +2690,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Assign); i { case 0: return &v.state @@ -2729,7 +2702,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Call); i { case 0: return &v.state @@ -2741,7 +2714,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ClassDef); i { case 0: return &v.state @@ -2753,7 +2726,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Comment); i { case 0: return &v.state @@ -2765,7 +2738,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Compare); i { case 0: return &v.state @@ -2777,7 +2750,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Constant); i { case 0: return &v.state @@ -2789,7 +2762,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Dict); i { case 0: return &v.state @@ -2801,7 +2774,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Expr); i { case 0: return &v.state @@ -2813,7 +2786,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*For); i { case 0: return &v.state @@ -2825,7 +2798,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FunctionDef); i { case 0: return &v.state @@ -2837,7 +2810,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*If); i { case 0: return &v.state @@ -2849,7 +2822,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Import); i { case 0: return &v.state @@ -2861,7 +2834,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ImportFrom); i { case 0: return &v.state @@ -2873,7 +2846,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ImportGroup); i { case 0: return &v.state @@ -2885,7 +2858,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Is); i { case 0: return &v.state @@ -2897,7 +2870,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Keyword); i { case 0: return &v.state @@ -2909,7 +2882,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Module); i { case 0: return &v.state @@ -2921,7 +2894,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Name); i { case 0: return &v.state @@ -2933,7 +2906,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Pass); i { case 0: return &v.state @@ -2945,7 +2918,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Return); i { case 0: return &v.state @@ -2957,7 +2930,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Subscript); i { case 0: return &v.state @@ -2969,7 +2942,7 @@ func file_python_ast_proto_init() { return nil } } - file_python_ast_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_ast_ast_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Yield); i { case 0: return &v.state @@ -2982,7 +2955,7 @@ func file_python_ast_proto_init() { } } } - file_python_ast_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_ast_ast_proto_msgTypes[0].OneofWrappers = []interface{}{ (*Node_ClassDef)(nil), (*Node_Import)(nil), (*Node_ImportFrom)(nil), @@ -3014,7 +2987,7 @@ func file_python_ast_proto_init() { (*Node_AsyncFor)(nil), (*Node_ImportGroup)(nil), } - file_python_ast_proto_msgTypes[14].OneofWrappers = []interface{}{ + file_ast_ast_proto_msgTypes[14].OneofWrappers = []interface{}{ (*Constant_Str)(nil), (*Constant_Int)(nil), (*Constant_None)(nil), @@ -3022,21 +2995,19 @@ func file_python_ast_proto_init() { type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ - // TinyGo does not support reflect, hardcode this for now - // GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - GoPackagePath: "github.com/tabbed/sqlc-gen-python/ast", - RawDescriptor: file_python_ast_proto_rawDesc, + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_ast_ast_proto_rawDesc, NumEnums: 0, NumMessages: 31, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_python_ast_proto_goTypes, - DependencyIndexes: file_python_ast_proto_depIdxs, - MessageInfos: file_python_ast_proto_msgTypes, + GoTypes: file_ast_ast_proto_goTypes, + DependencyIndexes: file_ast_ast_proto_depIdxs, + MessageInfos: file_ast_ast_proto_msgTypes, }.Build() - File_python_ast_proto = out.File - file_python_ast_proto_rawDesc = nil - file_python_ast_proto_goTypes = nil - file_python_ast_proto_depIdxs = nil + File_ast_ast_proto = out.File + file_ast_ast_proto_rawDesc = nil + file_ast_ast_proto_goTypes = nil + file_ast_ast_proto_depIdxs = nil } diff --git a/internal/config.go b/internal/config.go index 009cb04..1a8a565 100644 --- a/internal/config.go +++ b/internal/config.go @@ -7,6 +7,7 @@ type Config struct { Package string `json:"package"` Out string `json:"out"` EmitPydanticModels bool `json:"emit_pydantic_models"` + EmitStrEnum bool `json:"emit_str_enum"` QueryParameterLimit *int32 `json:"query_parameter_limit"` InflectionExcludeTableNames []string `json:"inflection_exclude_table_names"` } diff --git a/internal/config_easyjson.go b/internal/config_easyjson.go deleted file mode 100644 index 9b5451f..0000000 --- a/internal/config_easyjson.go +++ /dev/null @@ -1,178 +0,0 @@ -// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. - -package python - -import ( - json "encoding/json" - easyjson "github.com/mailru/easyjson" - jlexer "github.com/mailru/easyjson/jlexer" - jwriter "github.com/mailru/easyjson/jwriter" -) - -// suppress unused package warning -var ( - _ *json.RawMessage - _ *jlexer.Lexer - _ *jwriter.Writer - _ easyjson.Marshaler -) - -func easyjson6615c02eDecodeGithubComTabbedSqlcGoCmdSqlcGenPython(in *jlexer.Lexer, out *Config) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeFieldName(false) - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "emit_exact_table_names": - out.EmitExactTableNames = bool(in.Bool()) - case "emit_sync_querier": - out.EmitSyncQuerier = bool(in.Bool()) - case "emit_async_querier": - out.EmitAsyncQuerier = bool(in.Bool()) - case "package": - out.Package = string(in.String()) - case "out": - out.Out = string(in.String()) - case "emit_pydantic_models": - out.EmitPydanticModels = bool(in.Bool()) - case "query_parameter_limit": - if in.IsNull() { - in.Skip() - out.QueryParameterLimit = nil - } else { - if out.QueryParameterLimit == nil { - out.QueryParameterLimit = new(int32) - } - *out.QueryParameterLimit = int32(in.Int32()) - } - case "inflection_exclude_table_names": - if in.IsNull() { - in.Skip() - out.InflectionExcludeTableNames = nil - } else { - in.Delim('[') - if out.InflectionExcludeTableNames == nil { - if !in.IsDelim(']') { - out.InflectionExcludeTableNames = make([]string, 0, 4) - } else { - out.InflectionExcludeTableNames = []string{} - } - } else { - out.InflectionExcludeTableNames = (out.InflectionExcludeTableNames)[:0] - } - for !in.IsDelim(']') { - var v1 string - v1 = string(in.String()) - out.InflectionExcludeTableNames = append(out.InflectionExcludeTableNames, v1) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson6615c02eEncodeGithubComTabbedSqlcGoCmdSqlcGenPython(out *jwriter.Writer, in Config) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"emit_exact_table_names\":" - out.RawString(prefix[1:]) - out.Bool(bool(in.EmitExactTableNames)) - } - { - const prefix string = ",\"emit_sync_querier\":" - out.RawString(prefix) - out.Bool(bool(in.EmitSyncQuerier)) - } - { - const prefix string = ",\"emit_async_querier\":" - out.RawString(prefix) - out.Bool(bool(in.EmitAsyncQuerier)) - } - { - const prefix string = ",\"package\":" - out.RawString(prefix) - out.String(string(in.Package)) - } - { - const prefix string = ",\"out\":" - out.RawString(prefix) - out.String(string(in.Out)) - } - { - const prefix string = ",\"emit_pydantic_models\":" - out.RawString(prefix) - out.Bool(bool(in.EmitPydanticModels)) - } - { - const prefix string = ",\"query_parameter_limit\":" - out.RawString(prefix) - if in.QueryParameterLimit == nil { - out.RawString("null") - } else { - out.Int32(int32(*in.QueryParameterLimit)) - } - } - { - const prefix string = ",\"inflection_exclude_table_names\":" - out.RawString(prefix) - if in.InflectionExcludeTableNames == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v2, v3 := range in.InflectionExcludeTableNames { - if v2 > 0 { - out.RawByte(',') - } - out.String(string(v3)) - } - out.RawByte(']') - } - } - out.RawByte('}') -} - -// MarshalJSON supports json.Marshaler interface -func (v Config) MarshalJSON() ([]byte, error) { - w := jwriter.Writer{} - easyjson6615c02eEncodeGithubComTabbedSqlcGoCmdSqlcGenPython(&w, v) - return w.Buffer.BuildBytes(), w.Error -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v Config) MarshalEasyJSON(w *jwriter.Writer) { - easyjson6615c02eEncodeGithubComTabbedSqlcGoCmdSqlcGenPython(w, v) -} - -// UnmarshalJSON supports json.Unmarshaler interface -func (v *Config) UnmarshalJSON(data []byte) error { - r := jlexer.Lexer{Data: data} - easyjson6615c02eDecodeGithubComTabbedSqlcGoCmdSqlcGenPython(&r, v) - return r.Error() -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *Config) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson6615c02eDecodeGithubComTabbedSqlcGoCmdSqlcGenPython(l, v) -} diff --git a/internal/endtoend/endtoend_test.go b/internal/endtoend/endtoend_test.go new file mode 100644 index 0000000..bd66c27 --- /dev/null +++ b/internal/endtoend/endtoend_test.go @@ -0,0 +1,111 @@ +package endtoend + +import ( + "bytes" + "crypto/sha256" + "fmt" + "os" + "os/exec" + "path/filepath" + "regexp" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func FindTests(t *testing.T, root string) []string { + t.Helper() + var dirs []string + err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.Name() == "sqlc.yaml" { + dirs = append(dirs, filepath.Dir(path)) + return filepath.SkipDir + } + return nil + }) + if err != nil { + t.Fatal(err) + } + return dirs +} + +func LookPath(t *testing.T, cmds ...string) string { + t.Helper() + for _, cmd := range cmds { + path, err := exec.LookPath(cmd) + if err == nil { + return path + } + } + t.Fatalf("could not find command(s) in $PATH: %s", cmds) + return "" +} + +func ExpectedOutput(t *testing.T, dir string) []byte { + t.Helper() + path := filepath.Join(dir, "stderr.txt") + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + return []byte{} + } else { + t.Fatal(err) + } + } + output, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + return output +} + +var pattern = regexp.MustCompile(`sha256: ".*"`) + +func TestGenerate(t *testing.T) { + // The SHA256 is required, so we calculate it and then update all of the + // sqlc.yaml files. + // TODO: Remove this once sqlc v1.24.0 has been released + wasmpath := filepath.Join("..", "..", "bin", "sqlc-gen-python.wasm") + if _, err := os.Stat(wasmpath); err != nil { + t.Fatalf("sqlc-gen-python.wasm not found: %s", err) + } + wmod, err := os.ReadFile(wasmpath) + if err != nil { + t.Fatal(err) + } + sum := sha256.Sum256(wmod) + sha256 := fmt.Sprintf("%x", sum) + + sqlc := LookPath(t, "sqlc-dev", "sqlc") + + for _, dir := range FindTests(t, "testdata") { + dir := dir + t.Run(dir, func(t *testing.T) { + // Check if sqlc.yaml has the correct SHA256 for the plugin. If not, update the file + // TODO: Remove this once sqlc v1.24.0 has been released + yaml, err := os.ReadFile(filepath.Join(dir, "sqlc.yaml")) + if err != nil { + t.Fatal(err) + } + if !bytes.Contains(yaml, []byte(sha256)) { + yaml = pattern.ReplaceAllLiteral(yaml, []byte(`sha256: "`+sha256+`"`)) + if err := os.WriteFile(filepath.Join(dir, "sqlc.yaml"), yaml, 0644); err != nil { + t.Fatal(err) + } + } + + want := ExpectedOutput(t, dir) + cmd := exec.Command(sqlc, "diff") + cmd.Dir = dir + got, err := cmd.CombinedOutput() + if diff := cmp.Diff(string(want), string(got)); diff != "" { + t.Errorf("sqlc diff mismatch (-want +got):\n%s", diff) + } + if len(want) == 0 && err != nil { + t.Error(err) + } + }) + } +} diff --git a/internal/endtoend/testdata/emit_pydantic_models/db/__init__.py b/internal/endtoend/testdata/emit_pydantic_models/db/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/internal/endtoend/testdata/emit_pydantic_models/db/models.py b/internal/endtoend/testdata/emit_pydantic_models/db/models.py new file mode 100644 index 0000000..7676e5c --- /dev/null +++ b/internal/endtoend/testdata/emit_pydantic_models/db/models.py @@ -0,0 +1,11 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import pydantic +from typing import Optional + + +class Author(pydantic.BaseModel): + id: int + name: str + bio: Optional[str] diff --git a/internal/endtoend/testdata/emit_pydantic_models/db/query.py b/internal/endtoend/testdata/emit_pydantic_models/db/query.py new file mode 100644 index 0000000..6f5b76f --- /dev/null +++ b/internal/endtoend/testdata/emit_pydantic_models/db/query.py @@ -0,0 +1,112 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +from typing import AsyncIterator, Iterator, Optional + +import sqlalchemy +import sqlalchemy.ext.asyncio + +from db import models + + +CREATE_AUTHOR = """-- name: create_author \\:one +INSERT INTO authors ( + name, bio +) VALUES ( + :p1, :p2 +) +RETURNING id, name, bio +""" + + +DELETE_AUTHOR = """-- name: delete_author \\:exec +DELETE FROM authors +WHERE id = :p1 +""" + + +GET_AUTHOR = """-- name: get_author \\:one +SELECT id, name, bio FROM authors +WHERE id = :p1 LIMIT 1 +""" + + +LIST_AUTHORS = """-- name: list_authors \\:many +SELECT id, name, bio FROM authors +ORDER BY name +""" + + +class Querier: + def __init__(self, conn: sqlalchemy.engine.Connection): + self._conn = conn + + def create_author(self, *, name: str, bio: Optional[str]) -> Optional[models.Author]: + row = self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name, "p2": bio}).first() + if row is None: + return None + return models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + def delete_author(self, *, id: int) -> None: + self._conn.execute(sqlalchemy.text(DELETE_AUTHOR), {"p1": id}) + + def get_author(self, *, id: int) -> Optional[models.Author]: + row = self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": id}).first() + if row is None: + return None + return models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + def list_authors(self) -> Iterator[models.Author]: + result = self._conn.execute(sqlalchemy.text(LIST_AUTHORS)) + for row in result: + yield models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def create_author(self, *, name: str, bio: Optional[str]) -> Optional[models.Author]: + row = (await self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name, "p2": bio})).first() + if row is None: + return None + return models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + async def delete_author(self, *, id: int) -> None: + await self._conn.execute(sqlalchemy.text(DELETE_AUTHOR), {"p1": id}) + + async def get_author(self, *, id: int) -> Optional[models.Author]: + row = (await self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": id})).first() + if row is None: + return None + return models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) + + async def list_authors(self) -> AsyncIterator[models.Author]: + result = await self._conn.stream(sqlalchemy.text(LIST_AUTHORS)) + async for row in result: + yield models.Author( + id=row[0], + name=row[1], + bio=row[2], + ) diff --git a/internal/endtoend/testdata/emit_pydantic_models/query.sql b/internal/endtoend/testdata/emit_pydantic_models/query.sql new file mode 100644 index 0000000..75e38b2 --- /dev/null +++ b/internal/endtoend/testdata/emit_pydantic_models/query.sql @@ -0,0 +1,19 @@ +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +) +RETURNING *; + +-- name: DeleteAuthor :exec +DELETE FROM authors +WHERE id = $1; diff --git a/internal/endtoend/testdata/emit_pydantic_models/schema.sql b/internal/endtoend/testdata/emit_pydantic_models/schema.sql new file mode 100644 index 0000000..b4fad78 --- /dev/null +++ b/internal/endtoend/testdata/emit_pydantic_models/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/emit_pydantic_models/sqlc.yaml b/internal/endtoend/testdata/emit_pydantic_models/sqlc.yaml new file mode 100644 index 0000000..beae200 --- /dev/null +++ b/internal/endtoend/testdata/emit_pydantic_models/sqlc.yaml @@ -0,0 +1,18 @@ +version: '2' +plugins: +- name: py + wasm: + url: file://../../../../bin/sqlc-gen-python.wasm + sha256: "d6846ffad948181e611e883cedd2d2be66e091edc1273a0abc6c9da18399e0ca" +sql: +- schema: schema.sql + queries: query.sql + engine: postgresql + codegen: + - plugin: py + out: db + options: + package: db + emit_sync_querier: true + emit_async_querier: true + emit_pydantic_models: true \ No newline at end of file diff --git a/internal/endtoend/testdata/emit_str_enum/db/models.py b/internal/endtoend/testdata/emit_str_enum/db/models.py new file mode 100644 index 0000000..5fdf754 --- /dev/null +++ b/internal/endtoend/testdata/emit_str_enum/db/models.py @@ -0,0 +1,19 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses +import enum +from typing import Optional + + +class BookStatus(enum.StrEnum): + AVAILABLE = "available" + CHECKED_OUT = "checked_out" + OVERDUE = "overdue" + + +@dataclasses.dataclass() +class Book: + id: int + title: str + status: Optional[BookStatus] diff --git a/internal/endtoend/testdata/emit_str_enum/db/query.py b/internal/endtoend/testdata/emit_str_enum/db/query.py new file mode 100644 index 0000000..8082889 --- /dev/null +++ b/internal/endtoend/testdata/emit_str_enum/db/query.py @@ -0,0 +1,111 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +from typing import AsyncIterator, Iterator, Optional + +import sqlalchemy +import sqlalchemy.ext.asyncio + +from db import models + + +CREATE_BOOK = """-- name: create_book \\:one +INSERT INTO books ( + title, status +) VALUES ( + :p1, :p2 +) RETURNING id, title, status +""" + + +DELETE_BOOK = """-- name: delete_book \\:exec +DELETE FROM books +WHERE id = :p1 +""" + + +GET_BOOK = """-- name: get_book \\:one +SELECT id, title, status FROM books +WHERE id = :p1 LIMIT 1 +""" + + +LIST_BOOKS = """-- name: list_books \\:many +SELECT id, title, status FROM books +ORDER BY title +""" + + +class Querier: + def __init__(self, conn: sqlalchemy.engine.Connection): + self._conn = conn + + def create_book(self, *, title: str, status: Optional[models.BookStatus]) -> Optional[models.Book]: + row = self._conn.execute(sqlalchemy.text(CREATE_BOOK), {"p1": title, "p2": status}).first() + if row is None: + return None + return models.Book( + id=row[0], + title=row[1], + status=row[2], + ) + + def delete_book(self, *, id: int) -> None: + self._conn.execute(sqlalchemy.text(DELETE_BOOK), {"p1": id}) + + def get_book(self, *, id: int) -> Optional[models.Book]: + row = self._conn.execute(sqlalchemy.text(GET_BOOK), {"p1": id}).first() + if row is None: + return None + return models.Book( + id=row[0], + title=row[1], + status=row[2], + ) + + def list_books(self) -> Iterator[models.Book]: + result = self._conn.execute(sqlalchemy.text(LIST_BOOKS)) + for row in result: + yield models.Book( + id=row[0], + title=row[1], + status=row[2], + ) + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def create_book(self, *, title: str, status: Optional[models.BookStatus]) -> Optional[models.Book]: + row = (await self._conn.execute(sqlalchemy.text(CREATE_BOOK), {"p1": title, "p2": status})).first() + if row is None: + return None + return models.Book( + id=row[0], + title=row[1], + status=row[2], + ) + + async def delete_book(self, *, id: int) -> None: + await self._conn.execute(sqlalchemy.text(DELETE_BOOK), {"p1": id}) + + async def get_book(self, *, id: int) -> Optional[models.Book]: + row = (await self._conn.execute(sqlalchemy.text(GET_BOOK), {"p1": id})).first() + if row is None: + return None + return models.Book( + id=row[0], + title=row[1], + status=row[2], + ) + + async def list_books(self) -> AsyncIterator[models.Book]: + result = await self._conn.stream(sqlalchemy.text(LIST_BOOKS)) + async for row in result: + yield models.Book( + id=row[0], + title=row[1], + status=row[2], + ) diff --git a/internal/endtoend/testdata/emit_str_enum/query.sql b/internal/endtoend/testdata/emit_str_enum/query.sql new file mode 100644 index 0000000..61142f7 --- /dev/null +++ b/internal/endtoend/testdata/emit_str_enum/query.sql @@ -0,0 +1,18 @@ +-- name: GetBook :one +SELECT * FROM books +WHERE id = $1 LIMIT 1; + +-- name: ListBooks :many +SELECT * FROM books +ORDER BY title; + +-- name: CreateBook :one +INSERT INTO books ( + title, status +) VALUES ( + $1, $2 +) RETURNING *; + +-- name: DeleteBook :exec +DELETE FROM books +WHERE id = $1; diff --git a/internal/endtoend/testdata/emit_str_enum/schema.sql b/internal/endtoend/testdata/emit_str_enum/schema.sql new file mode 100644 index 0000000..6842b27 --- /dev/null +++ b/internal/endtoend/testdata/emit_str_enum/schema.sql @@ -0,0 +1,8 @@ +CREATE TYPE book_status AS ENUM ('available', 'checked_out', 'overdue'); + + +CREATE TABLE books ( + id BIGSERIAL PRIMARY KEY, + title text NOT NULL, + status book_status DEFAULT 'available' +); diff --git a/internal/endtoend/testdata/emit_str_enum/sqlc.yaml b/internal/endtoend/testdata/emit_str_enum/sqlc.yaml new file mode 100644 index 0000000..04e3feb --- /dev/null +++ b/internal/endtoend/testdata/emit_str_enum/sqlc.yaml @@ -0,0 +1,19 @@ +version: "2" +plugins: + - name: py + wasm: + url: file://../../../../bin/sqlc-gen-python.wasm + sha256: "d6846ffad948181e611e883cedd2d2be66e091edc1273a0abc6c9da18399e0ca" +sql: + - schema: schema.sql + queries: query.sql + engine: postgresql + codegen: + - plugin: py + out: db + options: + package: db + emit_sync_querier: true + emit_async_querier: true + emit_str_enum: true + diff --git a/internal/endtoend/testdata/exec_result/python/models.py b/internal/endtoend/testdata/exec_result/python/models.py new file mode 100644 index 0000000..034fb2d --- /dev/null +++ b/internal/endtoend/testdata/exec_result/python/models.py @@ -0,0 +1,9 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses + + +@dataclasses.dataclass() +class Bar: + id: int diff --git a/internal/endtoend/testdata/exec_result/python/query.py b/internal/endtoend/testdata/exec_result/python/query.py new file mode 100644 index 0000000..b68ce39 --- /dev/null +++ b/internal/endtoend/testdata/exec_result/python/query.py @@ -0,0 +1,29 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +import sqlalchemy +import sqlalchemy.ext.asyncio + +from querytest import models + + +DELETE_BAR_BY_ID = """-- name: delete_bar_by_id \\:execresult +DELETE FROM bar WHERE id = :p1 +""" + + +class Querier: + def __init__(self, conn: sqlalchemy.engine.Connection): + self._conn = conn + + def delete_bar_by_id(self, *, id: int) -> sqlalchemy.engine.Result: + return self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id}) + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def delete_bar_by_id(self, *, id: int) -> sqlalchemy.engine.Result: + return await self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id}) diff --git a/internal/endtoend/testdata/exec_result/query.sql b/internal/endtoend/testdata/exec_result/query.sql new file mode 100644 index 0000000..7391778 --- /dev/null +++ b/internal/endtoend/testdata/exec_result/query.sql @@ -0,0 +1,2 @@ +-- name: DeleteBarByID :execresult +DELETE FROM bar WHERE id = $1; diff --git a/internal/endtoend/testdata/exec_result/schema.sql b/internal/endtoend/testdata/exec_result/schema.sql new file mode 100644 index 0000000..638370a --- /dev/null +++ b/internal/endtoend/testdata/exec_result/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE bar (id serial not null); + diff --git a/internal/endtoend/testdata/exec_result/sqlc.yaml b/internal/endtoend/testdata/exec_result/sqlc.yaml new file mode 100644 index 0000000..ddffc83 --- /dev/null +++ b/internal/endtoend/testdata/exec_result/sqlc.yaml @@ -0,0 +1,17 @@ +version: '2' +plugins: +- name: py + wasm: + url: file://../../../../bin/sqlc-gen-python.wasm + sha256: "d6846ffad948181e611e883cedd2d2be66e091edc1273a0abc6c9da18399e0ca" +sql: +- schema: schema.sql + queries: query.sql + engine: postgresql + codegen: + - plugin: py + out: python + options: + package: querytest + emit_sync_querier: true + emit_async_querier: true diff --git a/internal/endtoend/testdata/exec_rows/python/models.py b/internal/endtoend/testdata/exec_rows/python/models.py new file mode 100644 index 0000000..034fb2d --- /dev/null +++ b/internal/endtoend/testdata/exec_rows/python/models.py @@ -0,0 +1,9 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses + + +@dataclasses.dataclass() +class Bar: + id: int diff --git a/internal/endtoend/testdata/exec_rows/python/query.py b/internal/endtoend/testdata/exec_rows/python/query.py new file mode 100644 index 0000000..7a9b2a6 --- /dev/null +++ b/internal/endtoend/testdata/exec_rows/python/query.py @@ -0,0 +1,31 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +import sqlalchemy +import sqlalchemy.ext.asyncio + +from querytest import models + + +DELETE_BAR_BY_ID = """-- name: delete_bar_by_id \\:execrows +DELETE FROM bar WHERE id = :p1 +""" + + +class Querier: + def __init__(self, conn: sqlalchemy.engine.Connection): + self._conn = conn + + def delete_bar_by_id(self, *, id: int) -> int: + result = self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id}) + return result.rowcount + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def delete_bar_by_id(self, *, id: int) -> int: + result = await self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id}) + return result.rowcount diff --git a/internal/endtoend/testdata/exec_rows/query.sql b/internal/endtoend/testdata/exec_rows/query.sql new file mode 100644 index 0000000..94d2d09 --- /dev/null +++ b/internal/endtoend/testdata/exec_rows/query.sql @@ -0,0 +1,2 @@ +-- name: DeleteBarByID :execrows +DELETE FROM bar WHERE id = $1; diff --git a/internal/endtoend/testdata/exec_rows/schema.sql b/internal/endtoend/testdata/exec_rows/schema.sql new file mode 100644 index 0000000..638370a --- /dev/null +++ b/internal/endtoend/testdata/exec_rows/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE bar (id serial not null); + diff --git a/internal/endtoend/testdata/exec_rows/sqlc.yaml b/internal/endtoend/testdata/exec_rows/sqlc.yaml new file mode 100644 index 0000000..ddffc83 --- /dev/null +++ b/internal/endtoend/testdata/exec_rows/sqlc.yaml @@ -0,0 +1,17 @@ +version: '2' +plugins: +- name: py + wasm: + url: file://../../../../bin/sqlc-gen-python.wasm + sha256: "d6846ffad948181e611e883cedd2d2be66e091edc1273a0abc6c9da18399e0ca" +sql: +- schema: schema.sql + queries: query.sql + engine: postgresql + codegen: + - plugin: py + out: python + options: + package: querytest + emit_sync_querier: true + emit_async_querier: true diff --git a/internal/endtoend/testdata/inflection_exclude_table_names/python/models.py b/internal/endtoend/testdata/inflection_exclude_table_names/python/models.py new file mode 100644 index 0000000..8ba8803 --- /dev/null +++ b/internal/endtoend/testdata/inflection_exclude_table_names/python/models.py @@ -0,0 +1,22 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses + + +@dataclasses.dataclass() +class Bar: + id: int + name: str + + +@dataclasses.dataclass() +class Exclusions: + id: int + name: str + + +@dataclasses.dataclass() +class MyData: + id: int + name: str diff --git a/internal/endtoend/testdata/inflection_exclude_table_names/python/query.py b/internal/endtoend/testdata/inflection_exclude_table_names/python/query.py new file mode 100644 index 0000000..1e1e161 --- /dev/null +++ b/internal/endtoend/testdata/inflection_exclude_table_names/python/query.py @@ -0,0 +1,89 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +from typing import Optional + +import sqlalchemy +import sqlalchemy.ext.asyncio + +from querytest import models + + +DELETE_BAR_BY_ID = """-- name: delete_bar_by_id \\:one +DELETE FROM bars WHERE id = :p1 RETURNING id, name +""" + + +DELETE_EXCLUSION_BY_ID = """-- name: delete_exclusion_by_id \\:one +DELETE FROM exclusions WHERE id = :p1 RETURNING id, name +""" + + +DELETE_MY_DATA_BY_ID = """-- name: delete_my_data_by_id \\:one +DELETE FROM my_data WHERE id = :p1 RETURNING id, name +""" + + +class Querier: + def __init__(self, conn: sqlalchemy.engine.Connection): + self._conn = conn + + def delete_bar_by_id(self, *, id: int) -> Optional[models.Bar]: + row = self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id}).first() + if row is None: + return None + return models.Bar( + id=row[0], + name=row[1], + ) + + def delete_exclusion_by_id(self, *, id: int) -> Optional[models.Exclusions]: + row = self._conn.execute(sqlalchemy.text(DELETE_EXCLUSION_BY_ID), {"p1": id}).first() + if row is None: + return None + return models.Exclusions( + id=row[0], + name=row[1], + ) + + def delete_my_data_by_id(self, *, id: int) -> Optional[models.MyData]: + row = self._conn.execute(sqlalchemy.text(DELETE_MY_DATA_BY_ID), {"p1": id}).first() + if row is None: + return None + return models.MyData( + id=row[0], + name=row[1], + ) + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def delete_bar_by_id(self, *, id: int) -> Optional[models.Bar]: + row = (await self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id})).first() + if row is None: + return None + return models.Bar( + id=row[0], + name=row[1], + ) + + async def delete_exclusion_by_id(self, *, id: int) -> Optional[models.Exclusions]: + row = (await self._conn.execute(sqlalchemy.text(DELETE_EXCLUSION_BY_ID), {"p1": id})).first() + if row is None: + return None + return models.Exclusions( + id=row[0], + name=row[1], + ) + + async def delete_my_data_by_id(self, *, id: int) -> Optional[models.MyData]: + row = (await self._conn.execute(sqlalchemy.text(DELETE_MY_DATA_BY_ID), {"p1": id})).first() + if row is None: + return None + return models.MyData( + id=row[0], + name=row[1], + ) diff --git a/internal/endtoend/testdata/inflection_exclude_table_names/query.sql b/internal/endtoend/testdata/inflection_exclude_table_names/query.sql new file mode 100644 index 0000000..f279a10 --- /dev/null +++ b/internal/endtoend/testdata/inflection_exclude_table_names/query.sql @@ -0,0 +1,8 @@ +-- name: DeleteBarByID :one +DELETE FROM bars WHERE id = $1 RETURNING id, name; + +-- name: DeleteMyDataByID :one +DELETE FROM my_data WHERE id = $1 RETURNING id, name; + +-- name: DeleteExclusionByID :one +DELETE FROM exclusions WHERE id = $1 RETURNING id, name; diff --git a/internal/endtoend/testdata/inflection_exclude_table_names/schema.sql b/internal/endtoend/testdata/inflection_exclude_table_names/schema.sql new file mode 100644 index 0000000..ea5b797 --- /dev/null +++ b/internal/endtoend/testdata/inflection_exclude_table_names/schema.sql @@ -0,0 +1,4 @@ +CREATE TABLE bars (id serial not null, name text not null, primary key (id)); +CREATE TABLE my_data (id serial not null, name text not null, primary key (id)); +CREATE TABLE exclusions (id serial not null, name text not null, primary key (id)); + diff --git a/internal/endtoend/testdata/inflection_exclude_table_names/sqlc.yaml b/internal/endtoend/testdata/inflection_exclude_table_names/sqlc.yaml new file mode 100644 index 0000000..efbb150 --- /dev/null +++ b/internal/endtoend/testdata/inflection_exclude_table_names/sqlc.yaml @@ -0,0 +1,20 @@ +version: '2' +plugins: +- name: py + wasm: + url: file://../../../../bin/sqlc-gen-python.wasm + sha256: "d6846ffad948181e611e883cedd2d2be66e091edc1273a0abc6c9da18399e0ca" +sql: +- schema: schema.sql + queries: query.sql + engine: postgresql + codegen: + - plugin: py + out: python + options: + package: querytest + emit_sync_querier: true + emit_async_querier: true + inflection_exclude_table_names: + - my_data + - exclusions diff --git a/internal/endtoend/testdata/query_parameter_limit_two/python/models.py b/internal/endtoend/testdata/query_parameter_limit_two/python/models.py new file mode 100644 index 0000000..059675d --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_two/python/models.py @@ -0,0 +1,10 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses + + +@dataclasses.dataclass() +class Bar: + id: int + name: str diff --git a/internal/endtoend/testdata/query_parameter_limit_two/python/query.py b/internal/endtoend/testdata/query_parameter_limit_two/python/query.py new file mode 100644 index 0000000..e8b723e --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_two/python/query.py @@ -0,0 +1,44 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +import sqlalchemy +import sqlalchemy.ext.asyncio + +from querytest import models + + +DELETE_BAR_BY_ID = """-- name: delete_bar_by_id \\:execrows +DELETE FROM bar WHERE id = :p1 +""" + + +DELETE_BAR_BY_ID_AND_NAME = """-- name: delete_bar_by_id_and_name \\:execrows +DELETE FROM bar WHERE id = :p1 AND name = :p2 +""" + + +class Querier: + def __init__(self, conn: sqlalchemy.engine.Connection): + self._conn = conn + + def delete_bar_by_id(self, *, id: int) -> int: + result = self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id}) + return result.rowcount + + def delete_bar_by_id_and_name(self, *, id: int, name: str) -> int: + result = self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID_AND_NAME), {"p1": id, "p2": name}) + return result.rowcount + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def delete_bar_by_id(self, *, id: int) -> int: + result = await self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id}) + return result.rowcount + + async def delete_bar_by_id_and_name(self, *, id: int, name: str) -> int: + result = await self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID_AND_NAME), {"p1": id, "p2": name}) + return result.rowcount diff --git a/internal/endtoend/testdata/query_parameter_limit_two/query.sql b/internal/endtoend/testdata/query_parameter_limit_two/query.sql new file mode 100644 index 0000000..b96c66b --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_two/query.sql @@ -0,0 +1,5 @@ +-- name: DeleteBarByID :execrows +DELETE FROM bar WHERE id = $1; + +-- name: DeleteBarByIDAndName :execrows +DELETE FROM bar WHERE id = $1 AND name = $2; diff --git a/internal/endtoend/testdata/query_parameter_limit_two/schema.sql b/internal/endtoend/testdata/query_parameter_limit_two/schema.sql new file mode 100644 index 0000000..a27c312 --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_two/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE bar (id serial not null, name text not null, primary key (id)); + diff --git a/internal/endtoend/testdata/query_parameter_limit_two/sqlc.yaml b/internal/endtoend/testdata/query_parameter_limit_two/sqlc.yaml new file mode 100644 index 0000000..336bca7 --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_two/sqlc.yaml @@ -0,0 +1,18 @@ +version: '2' +plugins: +- name: py + wasm: + url: file://../../../../bin/sqlc-gen-python.wasm + sha256: "d6846ffad948181e611e883cedd2d2be66e091edc1273a0abc6c9da18399e0ca" +sql: +- schema: schema.sql + queries: query.sql + engine: postgresql + codegen: + - plugin: py + out: python + options: + package: querytest + emit_sync_querier: true + emit_async_querier: true + query_parameter_limit: 2 \ No newline at end of file diff --git a/internal/endtoend/testdata/query_parameter_limit_undefined/python/models.py b/internal/endtoend/testdata/query_parameter_limit_undefined/python/models.py new file mode 100644 index 0000000..30e80db --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_undefined/python/models.py @@ -0,0 +1,12 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses + + +@dataclasses.dataclass() +class Bar: + id: int + name1: str + name2: str + name3: str diff --git a/internal/endtoend/testdata/query_parameter_limit_undefined/python/query.py b/internal/endtoend/testdata/query_parameter_limit_undefined/python/query.py new file mode 100644 index 0000000..5a1fbbc --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_undefined/python/query.py @@ -0,0 +1,58 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +import sqlalchemy +import sqlalchemy.ext.asyncio + +from querytest import models + + +DELETE_BAR_BY_ID = """-- name: delete_bar_by_id \\:execrows +DELETE FROM bar WHERE id = :p1 +""" + + +DELETE_BAR_BY_ID_AND_NAME = """-- name: delete_bar_by_id_and_name \\:execrows +DELETE FROM bar +WHERE id = :p1 +AND name1 = :p2 +AND name2 = :p3 +AND name3 = :p4 +""" + + +class Querier: + def __init__(self, conn: sqlalchemy.engine.Connection): + self._conn = conn + + def delete_bar_by_id(self, *, id: int) -> int: + result = self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id}) + return result.rowcount + + def delete_bar_by_id_and_name(self, *, id: int, name1: str, name2: str, name3: str) -> int: + result = self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID_AND_NAME), { + "p1": id, + "p2": name1, + "p3": name2, + "p4": name3, + }) + return result.rowcount + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def delete_bar_by_id(self, *, id: int) -> int: + result = await self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": id}) + return result.rowcount + + async def delete_bar_by_id_and_name(self, *, id: int, name1: str, name2: str, name3: str) -> int: + result = await self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID_AND_NAME), { + "p1": id, + "p2": name1, + "p3": name2, + "p4": name3, + }) + return result.rowcount diff --git a/internal/endtoend/testdata/query_parameter_limit_undefined/query.sql b/internal/endtoend/testdata/query_parameter_limit_undefined/query.sql new file mode 100644 index 0000000..aea8511 --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_undefined/query.sql @@ -0,0 +1,10 @@ +-- name: DeleteBarByID :execrows +DELETE FROM bar WHERE id = $1; + +-- name: DeleteBarByIDAndName :execrows +DELETE FROM bar +WHERE id = $1 +AND name1 = $2 +AND name2 = $3 +AND name3 = $4 +; diff --git a/internal/endtoend/testdata/query_parameter_limit_undefined/schema.sql b/internal/endtoend/testdata/query_parameter_limit_undefined/schema.sql new file mode 100644 index 0000000..1d9131f --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_undefined/schema.sql @@ -0,0 +1,7 @@ +CREATE TABLE bar ( + id serial not null, + name1 text not null, + name2 text not null, + name3 text not null, + primary key (id)); + diff --git a/internal/endtoend/testdata/query_parameter_limit_undefined/sqlc.yaml b/internal/endtoend/testdata/query_parameter_limit_undefined/sqlc.yaml new file mode 100644 index 0000000..c20cd57 --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_undefined/sqlc.yaml @@ -0,0 +1,17 @@ +version: '2' +plugins: +- name: py + wasm: + url: file://../../../../bin/sqlc-gen-python.wasm + sha256: "d6846ffad948181e611e883cedd2d2be66e091edc1273a0abc6c9da18399e0ca" +sql: +- schema: schema.sql + queries: query.sql + engine: postgresql + codegen: + - plugin: py + out: python + options: + package: querytest + emit_sync_querier: true + emit_async_querier: true \ No newline at end of file diff --git a/internal/endtoend/testdata/query_parameter_limit_zero/python/models.py b/internal/endtoend/testdata/query_parameter_limit_zero/python/models.py new file mode 100644 index 0000000..059675d --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_zero/python/models.py @@ -0,0 +1,10 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +import dataclasses + + +@dataclasses.dataclass() +class Bar: + id: int + name: str diff --git a/internal/endtoend/testdata/query_parameter_limit_zero/python/query.py b/internal/endtoend/testdata/query_parameter_limit_zero/python/query.py new file mode 100644 index 0000000..47bd6a9 --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_zero/python/query.py @@ -0,0 +1,57 @@ +# Code generated by sqlc. DO NOT EDIT. +# versions: +# sqlc v1.28.0 +# source: query.sql +import dataclasses + +import sqlalchemy +import sqlalchemy.ext.asyncio + +from querytest import models + + +DELETE_BAR_BY_ID = """-- name: delete_bar_by_id \\:execrows +DELETE FROM bar WHERE id = :p1 +""" + + +@dataclasses.dataclass() +class DeleteBarByIDParams: + id: int + + +DELETE_BAR_BY_ID_AND_NAME = """-- name: delete_bar_by_id_and_name \\:execrows +DELETE FROM bar WHERE id = :p1 AND name = :p2 +""" + + +@dataclasses.dataclass() +class DeleteBarByIDAndNameParams: + id: int + name: str + + +class Querier: + def __init__(self, conn: sqlalchemy.engine.Connection): + self._conn = conn + + def delete_bar_by_id(self, arg: DeleteBarByIDParams) -> int: + result = self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": arg.id}) + return result.rowcount + + def delete_bar_by_id_and_name(self, arg: DeleteBarByIDAndNameParams) -> int: + result = self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID_AND_NAME), {"p1": arg.id, "p2": arg.name}) + return result.rowcount + + +class AsyncQuerier: + def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection): + self._conn = conn + + async def delete_bar_by_id(self, arg: DeleteBarByIDParams) -> int: + result = await self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID), {"p1": arg.id}) + return result.rowcount + + async def delete_bar_by_id_and_name(self, arg: DeleteBarByIDAndNameParams) -> int: + result = await self._conn.execute(sqlalchemy.text(DELETE_BAR_BY_ID_AND_NAME), {"p1": arg.id, "p2": arg.name}) + return result.rowcount diff --git a/internal/endtoend/testdata/query_parameter_limit_zero/query.sql b/internal/endtoend/testdata/query_parameter_limit_zero/query.sql new file mode 100644 index 0000000..b96c66b --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_zero/query.sql @@ -0,0 +1,5 @@ +-- name: DeleteBarByID :execrows +DELETE FROM bar WHERE id = $1; + +-- name: DeleteBarByIDAndName :execrows +DELETE FROM bar WHERE id = $1 AND name = $2; diff --git a/internal/endtoend/testdata/query_parameter_limit_zero/schema.sql b/internal/endtoend/testdata/query_parameter_limit_zero/schema.sql new file mode 100644 index 0000000..a27c312 --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_zero/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE bar (id serial not null, name text not null, primary key (id)); + diff --git a/internal/endtoend/testdata/query_parameter_limit_zero/sqlc.yaml b/internal/endtoend/testdata/query_parameter_limit_zero/sqlc.yaml new file mode 100644 index 0000000..6e2cdeb --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit_zero/sqlc.yaml @@ -0,0 +1,18 @@ +version: '2' +plugins: +- name: py + wasm: + url: file://../../../../bin/sqlc-gen-python.wasm + sha256: "d6846ffad948181e611e883cedd2d2be66e091edc1273a0abc6c9da18399e0ca" +sql: +- schema: schema.sql + queries: query.sql + engine: postgresql + codegen: + - plugin: py + out: python + options: + package: querytest + emit_sync_querier: true + emit_async_querier: true + query_parameter_limit: 0 diff --git a/internal/endtoend/testdata/query_parameter_no_limit/query.sql b/internal/endtoend/testdata/query_parameter_no_limit/query.sql new file mode 100644 index 0000000..b96c66b --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_no_limit/query.sql @@ -0,0 +1,5 @@ +-- name: DeleteBarByID :execrows +DELETE FROM bar WHERE id = $1; + +-- name: DeleteBarByIDAndName :execrows +DELETE FROM bar WHERE id = $1 AND name = $2; diff --git a/internal/endtoend/testdata/query_parameter_no_limit/schema.sql b/internal/endtoend/testdata/query_parameter_no_limit/schema.sql new file mode 100644 index 0000000..fd3ca97 --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_no_limit/schema.sql @@ -0,0 +1 @@ +CREATE TABLE bar (id serial not null, name text not null, primary key (id)); \ No newline at end of file diff --git a/internal/endtoend/testdata/query_parameter_no_limit/sqlc.yaml b/internal/endtoend/testdata/query_parameter_no_limit/sqlc.yaml new file mode 100644 index 0000000..c432e4f --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_no_limit/sqlc.yaml @@ -0,0 +1,18 @@ +version: '2' +plugins: +- name: py + wasm: + url: file://../../../../bin/sqlc-gen-python.wasm + sha256: "d6846ffad948181e611e883cedd2d2be66e091edc1273a0abc6c9da18399e0ca" +sql: +- schema: schema.sql + queries: query.sql + engine: postgresql + codegen: + - plugin: py + out: python + options: + package: querytest + emit_sync_querier: true + emit_async_querier: true + query_parameter_limit: -1 diff --git a/internal/endtoend/testdata/query_parameter_no_limit/stderr.txt b/internal/endtoend/testdata/query_parameter_no_limit/stderr.txt new file mode 100644 index 0000000..efed0cc --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_no_limit/stderr.txt @@ -0,0 +1,2 @@ +# package py +error generating code: error generating output: invalid query parameter limit diff --git a/internal/gen.go b/internal/gen.go index ce3d2e0..6e50fae 100644 --- a/internal/gen.go +++ b/internal/gen.go @@ -2,6 +2,7 @@ package python import ( "context" + json "encoding/json" "errors" "fmt" "log" @@ -9,15 +10,14 @@ import ( "sort" "strings" - easyjson "github.com/mailru/easyjson" - plugin "github.com/tabbed/sqlc-go/codegen" - "github.com/tabbed/sqlc-go/metadata" - "github.com/tabbed/sqlc-go/sdk" + "github.com/sqlc-dev/plugin-sdk-go/metadata" + "github.com/sqlc-dev/plugin-sdk-go/plugin" + "github.com/sqlc-dev/plugin-sdk-go/sdk" - pyast "github.com/tabbed/sqlc-gen-python/internal/ast" - "github.com/tabbed/sqlc-gen-python/internal/inflection" - "github.com/tabbed/sqlc-gen-python/internal/poet" - pyprint "github.com/tabbed/sqlc-gen-python/internal/printer" + pyast "github.com/sqlc-dev/sqlc-gen-python/internal/ast" + "github.com/sqlc-dev/sqlc-gen-python/internal/inflection" + "github.com/sqlc-dev/sqlc-gen-python/internal/poet" + pyprint "github.com/sqlc-dev/sqlc-gen-python/internal/printer" ) type Constant struct { @@ -180,7 +180,7 @@ func (q Query) ArgDictNode() *pyast.Node { } } -func makePyType(req *plugin.CodeGenRequest, col *plugin.Column) pyType { +func makePyType(req *plugin.GenerateRequest, col *plugin.Column) pyType { typ := pyInnerType(req, col) return pyType{ InnerType: typ, @@ -189,21 +189,7 @@ func makePyType(req *plugin.CodeGenRequest, col *plugin.Column) pyType { } } -func pyInnerType(req *plugin.CodeGenRequest, col *plugin.Column) string { - columnType := sdk.DataType(col.Type) - for _, oride := range req.Settings.Overrides { - if !pyTypeIsSet(oride.PythonType) { - continue - } - sameTable := sdk.Matches(oride, col.Table, req.Catalog.DefaultSchema) - if oride.Column != "" && sdk.MatchString(oride.ColumnName, col.Name) && sameTable { - return pyTypeString(oride.PythonType) - } - if oride.DbType != "" && oride.DbType == columnType && oride.Nullable != (col.NotNull || col.IsArray) { - return pyTypeString(oride.PythonType) - } - } - +func pyInnerType(req *plugin.GenerateRequest, col *plugin.Column) string { switch req.Settings.Engine { case "postgresql": return postgresType(req, col) @@ -214,9 +200,6 @@ func pyInnerType(req *plugin.CodeGenRequest, col *plugin.Column) string { } func modelName(name string, settings *plugin.Settings) string { - if rename := settings.Rename[name]; rename != "" { - return rename - } out := "" for _, p := range strings.Split(name, "_") { out += strings.Title(p) @@ -243,7 +226,7 @@ func pyEnumValueName(value string) string { return strings.ToUpper(id) } -func buildEnums(req *plugin.CodeGenRequest) []Enum { +func buildEnums(req *plugin.GenerateRequest) []Enum { var enums []Enum for _, schema := range req.Catalog.Schemas { if schema.Name == "pg_catalog" || schema.Name == "information_schema" { @@ -276,7 +259,7 @@ func buildEnums(req *plugin.CodeGenRequest) []Enum { return enums } -func buildModels(conf Config, req *plugin.CodeGenRequest) []Struct { +func buildModels(conf Config, req *plugin.GenerateRequest) []Struct { var structs []Struct for _, schema := range req.Catalog.Schemas { if schema.Name == "pg_catalog" || schema.Name == "information_schema" { @@ -338,7 +321,7 @@ type pyColumn struct { *plugin.Column } -func columnsToStruct(req *plugin.CodeGenRequest, name string, columns []pyColumn) *Struct { +func columnsToStruct(req *plugin.GenerateRequest, name string, columns []pyColumn) *Struct { gs := Struct{ Name: name, } @@ -380,7 +363,7 @@ func sqlalchemySQL(s, engine string) string { return s } -func buildQueries(conf Config, req *plugin.CodeGenRequest, structs []Struct) ([]Query, error) { +func buildQueries(conf Config, req *plugin.GenerateRequest, structs []Struct) ([]Query, error) { qs := make([]Query, 0, len(req.Queries)) for _, query := range req.Queries { if query.Name == "" { @@ -698,12 +681,19 @@ func buildModelsTree(ctx *pyTmplCtx, i *importer) *pyast.Node { mod.Body = append(mod.Body, buildImportGroup(std), buildImportGroup(pkg)) for _, e := range ctx.Enums { + bases := []*pyast.Node{ + poet.Name("str"), + poet.Attribute(poet.Name("enum"), "Enum"), + } + if i.C.EmitStrEnum { + // override the bases to emit enum.StrEnum (only support in Python >=3.11) + bases = []*pyast.Node{ + poet.Attribute(poet.Name("enum"), "StrEnum"), + } + } def := &pyast.ClassDef{ - Name: e.Name, - Bases: []*pyast.Node{ - poet.Name("str"), - poet.Attribute(poet.Name("enum"), "Enum"), - }, + Name: e.Name, + Bases: bases, } if e.Comment != "" { def.Body = append(def.Body, &pyast.Node{ @@ -1091,10 +1081,10 @@ func HashComment(s string) string { return "# " + strings.ReplaceAll(s, "\n", "\n# ") } -func Generate(_ context.Context, req *plugin.Request) (*plugin.Response, error) { +func Generate(_ context.Context, req *plugin.GenerateRequest) (*plugin.GenerateResponse, error) { var conf Config if len(req.PluginOptions) > 0 { - if err := easyjson.Unmarshal(req.PluginOptions, &conf); err != nil { + if err := json.Unmarshal(req.PluginOptions, &conf); err != nil { return nil, err } } @@ -1107,11 +1097,10 @@ func Generate(_ context.Context, req *plugin.Request) (*plugin.Response, error) } i := &importer{ - Settings: req.Settings, - Models: models, - Queries: queries, - Enums: enums, - C: conf, + Models: models, + Queries: queries, + Enums: enums, + C: conf, } tctx := pyTmplCtx{ @@ -1143,7 +1132,7 @@ func Generate(_ context.Context, req *plugin.Request) (*plugin.Response, error) output[name] = string(result.Python) } - resp := plugin.Response{} + resp := plugin.GenerateResponse{} for filename, code := range output { resp.Files = append(resp.Files, &plugin.File{ diff --git a/internal/imports.go b/internal/imports.go index e5702d0..b88c58c 100644 --- a/internal/imports.go +++ b/internal/imports.go @@ -4,8 +4,6 @@ import ( "fmt" "sort" "strings" - - "github.com/tabbed/sqlc-go/codegen" ) type importSpec struct { @@ -14,17 +12,6 @@ type importSpec struct { Alias string } -func pyTypeIsSet(t *codegen.PythonType) bool { - return t.Module != "" || t.Name != "" -} - -func pyTypeString(t *codegen.PythonType) string { - if t.Name != "" && t.Module == "" { - return t.Name - } - return t.Module + "." + t.Name -} - func (i importSpec) String() string { if i.Alias != "" { if i.Name == "" { @@ -39,11 +26,10 @@ func (i importSpec) String() string { } type importer struct { - Settings *codegen.Settings - Models []Struct - Queries []Query - Enums []Enum - C Config + Models []Struct + Queries []Query + Enums []Enum + C Config } func structUses(name string, s Struct) bool { @@ -111,13 +97,6 @@ func (i *importer) modelImportSpecs() (map[string]importSpec, map[string]importS pkg := make(map[string]importSpec) - for _, o := range i.Settings.Overrides { - if pyTypeIsSet(o.PythonType) && o.PythonType.Module != "" { - if modelUses(pyTypeString(o.PythonType)) { - pkg[o.PythonType.Module] = importSpec{Module: o.PythonType.Module} - } - } - } return std, pkg } @@ -157,14 +136,6 @@ func (i *importer) queryImportSpecs(fileName string) (map[string]importSpec, map pkg["sqlalchemy.ext.asyncio"] = importSpec{Module: "sqlalchemy.ext.asyncio"} } - for _, o := range i.Settings.Overrides { - if pyTypeIsSet(o.PythonType) && o.PythonType.Module != "" { - if queryUses(pyTypeString(o.PythonType)) { - pkg[o.PythonType.Module] = importSpec{Module: o.PythonType.Module} - } - } - } - queryValueModelImports := func(qv QueryValue) { if qv.IsStruct() && qv.EmitStruct() { if i.C.EmitPydanticModels { diff --git a/internal/poet/builders.go b/internal/poet/builders.go index 34bc523..d38ed7c 100644 --- a/internal/poet/builders.go +++ b/internal/poet/builders.go @@ -1,6 +1,6 @@ package poet -import "github.com/tabbed/sqlc-gen-python/internal/ast" +import "github.com/sqlc-dev/sqlc-gen-python/internal/ast" func Alias(name string) *ast.Node { return &ast.Node{ diff --git a/internal/poet/poet.go b/internal/poet/poet.go index 1a90079..22b488c 100644 --- a/internal/poet/poet.go +++ b/internal/poet/poet.go @@ -1,7 +1,7 @@ package poet import ( - "github.com/tabbed/sqlc-gen-python/internal/ast" + "github.com/sqlc-dev/sqlc-gen-python/internal/ast" ) type proto interface { diff --git a/internal/postgresql_type.go b/internal/postgresql_type.go index 8579e90..3d0891b 100644 --- a/internal/postgresql_type.go +++ b/internal/postgresql_type.go @@ -3,11 +3,11 @@ package python import ( "log" - "github.com/tabbed/sqlc-go/codegen" - "github.com/tabbed/sqlc-go/sdk" + "github.com/sqlc-dev/plugin-sdk-go/plugin" + "github.com/sqlc-dev/plugin-sdk-go/sdk" ) -func postgresType(req *codegen.Request, col *codegen.Column) string { +func postgresType(req *plugin.GenerateRequest, col *plugin.Column) string { columnType := sdk.DataType(col.Type) switch columnType { diff --git a/internal/printer/printer.go b/internal/printer/printer.go index bc1ca5b..0660c6a 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -4,7 +4,7 @@ import ( "strconv" "strings" - "github.com/tabbed/sqlc-gen-python/internal/ast" + "github.com/sqlc-dev/sqlc-gen-python/internal/ast" ) type writer struct { diff --git a/internal/printer/printer_test.go b/internal/printer/printer_test.go index 2d4ae78..21823f9 100644 --- a/internal/printer/printer_test.go +++ b/internal/printer/printer_test.go @@ -6,7 +6,7 @@ import ( "github.com/google/go-cmp/cmp" - "github.com/tabbed/sqlc-gen-python/ast" + "github.com/sqlc-dev/sqlc-gen-python/internal/ast" ) type testcase struct { diff --git a/plugin/main.go b/plugin/main.go index 68b068c..9655347 100644 --- a/plugin/main.go +++ b/plugin/main.go @@ -1,9 +1,9 @@ package main import ( - "github.com/tabbed/sqlc-go/codegen" + "github.com/sqlc-dev/plugin-sdk-go/codegen" - python "github.com/tabbed/sqlc-gen-python/internal" + python "github.com/sqlc-dev/sqlc-gen-python/internal" ) func main() { diff --git a/protos/ast/ast.proto b/protos/ast/ast.proto new file mode 100644 index 0000000..a8daa62 --- /dev/null +++ b/protos/ast/ast.proto @@ -0,0 +1,242 @@ +syntax = "proto3"; + +package ast; + +option go_package = "github.com/sqlc-dev/sqlc-gen-python/internal/ast"; + +message Node { + oneof node { + ClassDef class_def = 1 [json_name="ClassDef"]; + Import import = 2 [json_name="Import"]; + ImportFrom import_from = 3 [json_name="ImportFrom"]; + Module module = 4 [json_name="Module"]; + Alias alias = 5 [json_name="Alias"]; + AnnAssign ann_assign = 6 [json_name="AnnAssign"]; + Name name = 7 [json_name="Name"]; + Subscript subscript = 8 [json_name="Subscript"]; + Attribute attribute = 9 [json_name="Attribute"]; + Constant constant = 10 [json_name="Constant"]; + Assign assign = 11 [json_name="Assign"]; + Comment comment = 12 [json_name="Comment"]; + Expr expr = 13 [json_name="Expr"]; + Call call = 14 [json_name="Call"]; + FunctionDef function_def = 15 [json_name="FunctionDef"]; + Arg arg = 16 [json_name="Arg"]; + Arguments arguments = 17 [json_name="Arguments"]; + AsyncFunctionDef async_function_def = 18 [json_name="AsyncFunctionDef"]; + Pass pass = 19 [json_name="Pass"]; + Dict dict = 20 [json_name="Dict"]; + If if = 21 [json_name="If"]; + Compare compare = 22 [json_name="Compare"]; + Return return = 23 [json_name="Return"]; + Is is = 24 [json_name="Is"]; + Keyword keyword = 25 [json_name="Keyword"]; + Yield yield = 26 [json_name="Yield"]; + For for = 27 [json_name="For"]; + Await await = 28 [json_name="Await"]; + AsyncFor async_for = 29 [json_name="AsyncFor"]; + ImportGroup import_group = 30 [json_name="ImportGroup"]; + } +} + +message Alias +{ + string name = 1 [json_name="name"]; +} + +message Await +{ + Node value = 1 [json_name="value"]; +} + +message Attribute +{ + Node value = 1 [json_name="value"]; + string attr = 2 [json_name="attr"]; +} + +message AnnAssign +{ + Name target = 1 [json_name="target"]; + Node annotation = 2 [json_name="annotation"]; + int32 simple = 3 [json_name="simple"]; + string Comment = 4 [json_name="comment"]; +} + +message Arg +{ + string arg = 1 [json_name="arg"]; + Node annotation = 2 [json_name="annotation"]; +} + +message Arguments +{ + repeated Arg args = 1 [json_name="args"]; + repeated Arg kw_only_args = 2 [json_name="kwonlyargs"]; +} + +message AsyncFor +{ + Node target = 1 [json_name="target"]; + Node iter = 2 [json_name="iter"]; + repeated Node body = 3 [json_name="body"]; +} + +message AsyncFunctionDef +{ + string name = 1 [json_name="name"]; + Arguments Args = 2 [json_name="args"]; + repeated Node body = 3 [json_name="body"]; + Node returns = 4 [json_name="returns"]; +} + +message Assign +{ + repeated Node targets = 1 [json_name="targets"]; + Node value = 2 [json_name="value"]; + string Comment = 3 [json_name="comment"]; +} + +message Call +{ + Node func = 1 [json_name="func"]; + repeated Node args = 2 [json_name="args"]; + repeated Keyword keywords = 3 [json_name="keywords"]; +} + +message ClassDef +{ + string name = 1 [json_name="name"]; + repeated Node bases = 2 [json_name="bases"]; + repeated Node keywords = 3 [json_name="keywords"]; + repeated Node body = 4 [json_name="body"]; + repeated Node decorator_list = 5 [json_name="decorator_list"]; +} + +// The Python ast module does not parse comments. It's not clear if this is the +// best way to support them in the AST +message Comment +{ + string text = 1 [json_name="text"]; +} + +message Compare +{ + Node left = 1 [json_name="left"]; + repeated Node ops = 2 [json_name="ops"]; + repeated Node comparators = 3 [json_name="comparators"]; +} + +message Constant +{ + oneof value { + string str = 1 [json_name="string"]; + int32 int = 2 [json_name="int"]; + bool none = 3 [json_name="none"]; + } +} + +message Dict +{ + repeated Node keys = 1 [json_name="keys"]; + repeated Node values = 2 [json_name="values"]; +} + +message Expr +{ + Node value = 1 [json_name="value"]; +} + +message For +{ + Node target = 1 [json_name="target"]; + Node iter = 2 [json_name="iter"]; + repeated Node body = 3 [json_name="body"]; +} + +message FunctionDef +{ + string name = 1 [json_name="name"]; + Arguments Args = 2 [json_name="args"]; + repeated Node body = 3 [json_name="body"]; + Node returns = 4 [json_name="returns"]; +} + +message If +{ + Node test = 1 [json_name="test"]; + repeated Node body = 2 [json_name="body"]; + repeated Node or_else = 3 [json_name="orelse"]; +} + +message Import +{ + repeated Node names = 1 [json_name="names"]; +} + +message ImportFrom +{ + string module = 1 [json_name="module"]; + repeated Node names = 2 [json_name="names"]; + int32 level = 3 [json_name="level"]; +} + +// Imports are always put at the top of the file, just after any module +// comments and docstrings, and before module globals and constants. +// +// Imports should be grouped in the following order: +// +// Standard library imports. +// Related third party imports. +// Local application/library specific imports. +// +// You should put a blank line between each group of imports. +// +// https://www.python.org/dev/peps/pep-0008/#imports +message ImportGroup +{ + repeated Node imports = 1 [json_name="imports"]; +} + +message Is +{ +} + +message Keyword +{ + string arg = 1 [json_name="arg"]; + Node value = 2 [json_name="value"]; +} + +message Module +{ + repeated Node body = 1 [json_name="body"]; +} + +message Name +{ + string id = 1 [json_name="id"]; +} + +message Pass +{ +} + +message Return +{ + Node value = 1 [json_name="value"]; +} + + +message Subscript +{ + Name value = 1 [json_name="value"]; + Node slice = 2 [json_name="slice"]; +} + +message Yield +{ + Node value = 1 [json_name="value"]; +} + + diff --git a/protos/buf.yaml b/protos/buf.yaml new file mode 100644 index 0000000..4c02d5a --- /dev/null +++ b/protos/buf.yaml @@ -0,0 +1,10 @@ +version: v1 +name: github.com/sqlc-dev/sqlc-gen-python +breaking: + use: + - FILE +lint: + use: + - DEFAULT + except: + - PACKAGE_VERSION_SUFFIX