diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6e5983..f6f780e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,8 @@ name: go on: push: + tags: + - v* branches: - main pull_request: @@ -21,3 +23,31 @@ jobs: - run: make test - run: sqlc diff working-directory: examples + + - name: Generate checksum + id: checksum + run: |- + echo "sha256=$(sha256sum bin/sqlc-gen-python.wasm | awk '{ print $1 }')" >> $GITHUB_OUTPUT + + - uses: actions/upload-artifact@v4 + with: + name: sqlc-gen-python + path: bin/sqlc-gen-python.wasm + + - name: Release the build on tag + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + body: | + # Configuration + ```yaml + version: '2' + plugins: + - name: py + wasm: + url: ${{ github.server_url }}/${{ github.repository}}/releases/download/${{ github.ref_name }}/sqlc-gen-python.wasm + sha256: ${{ steps.checksum.outputs.sha256 }} + ``` + generate_release_notes: true + files: | + bin/sqlc-gen-python.wasm \ No newline at end of file diff --git a/README.md b/README.md index d7e0d75..2806ed7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +# README ## Usage ```yaml @@ -16,6 +17,17 @@ sql: plugin: py options: package: authors - emit_sync_querier: true - emit_async_querier: true + emit_module: false + emit_generators: true + emit_async: false ``` + +## Multiple packages +If you have have a mono-repository setup you may want to split the output of queries and models. You can achieve this by using the `output_models_file_name` +and `output_querier_file` fields. If `output_models_file_name` is set to `null` for it will not output the `models.py` file. Setting `output_querier_file` to false will prevent outputting any query files. Combining these you can set one codegen to only output models while the other codegen outputs only queries. Make sure the `package` configuration is set equally so the query files import correctly the models. + +SQLC needs at least one query, so you may need to add a unused query like the following in your schema and reuse the `schema` as `queries`. +```sql +-- name: Skip :one +SELECT 1; +``` \ No newline at end of file diff --git a/internal/ast/ast.pb.go b/internal/ast/ast.pb.go index b0b1d3a..5eaa4fa 100644 --- a/internal/ast/ast.pb.go +++ b/internal/ast/ast.pb.go @@ -649,8 +649,9 @@ type AnnAssign struct { Target *Name `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` Annotation *Node `protobuf:"bytes,2,opt,name=annotation,proto3" json:"annotation,omitempty"` - Simple int32 `protobuf:"varint,3,opt,name=simple,proto3" json:"simple,omitempty"` - Comment string `protobuf:"bytes,4,opt,name=Comment,json=comment,proto3" json:"Comment,omitempty"` + Value *Node `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` + Simple int32 `protobuf:"varint,4,opt,name=simple,proto3" json:"simple,omitempty"` + Comment string `protobuf:"bytes,5,opt,name=Comment,json=comment,proto3" json:"Comment,omitempty"` } func (x *AnnAssign) Reset() { @@ -699,6 +700,13 @@ func (x *AnnAssign) GetAnnotation() *Node { return nil } +func (x *AnnAssign) GetValue() *Node { + if x != nil { + return x.Value + } + return nil +} + func (x *AnnAssign) GetSimple() int32 { if x != nil { return x.Simple @@ -2301,149 +2309,151 @@ var file_ast_ast_proto_rawDesc = []byte{ 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, + 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x74, 0x74, 0x72, 0x22, 0xac, 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, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, + 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, - 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, + 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, 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, 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, + 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, 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, + 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, 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, - 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, 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, + 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, 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, 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, + 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 ( @@ -2527,53 +2537,54 @@ var file_ast_ast_proto_depIdxs = []int32{ 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 - 76, // [76:76] is the sub-list for extension extendee - 0, // [0:76] is the sub-list for field type_name + 0, // 34: ast.AnnAssign.value:type_name -> ast.Node + 0, // 35: ast.Arg.annotation:type_name -> ast.Node + 5, // 36: ast.Arguments.args:type_name -> ast.Arg + 5, // 37: ast.Arguments.kw_only_args:type_name -> ast.Arg + 0, // 38: ast.AsyncFor.target:type_name -> ast.Node + 0, // 39: ast.AsyncFor.iter:type_name -> ast.Node + 0, // 40: ast.AsyncFor.body:type_name -> ast.Node + 6, // 41: ast.AsyncFunctionDef.Args:type_name -> ast.Arguments + 0, // 42: ast.AsyncFunctionDef.body:type_name -> ast.Node + 0, // 43: ast.AsyncFunctionDef.returns:type_name -> ast.Node + 0, // 44: ast.Assign.targets:type_name -> ast.Node + 0, // 45: ast.Assign.value:type_name -> ast.Node + 0, // 46: ast.Call.func:type_name -> ast.Node + 0, // 47: ast.Call.args:type_name -> ast.Node + 24, // 48: ast.Call.keywords:type_name -> ast.Keyword + 0, // 49: ast.ClassDef.bases:type_name -> ast.Node + 0, // 50: ast.ClassDef.keywords:type_name -> ast.Node + 0, // 51: ast.ClassDef.body:type_name -> ast.Node + 0, // 52: ast.ClassDef.decorator_list:type_name -> ast.Node + 0, // 53: ast.Compare.left:type_name -> ast.Node + 0, // 54: ast.Compare.ops:type_name -> ast.Node + 0, // 55: ast.Compare.comparators:type_name -> ast.Node + 0, // 56: ast.Dict.keys:type_name -> ast.Node + 0, // 57: ast.Dict.values:type_name -> ast.Node + 0, // 58: ast.Expr.value:type_name -> ast.Node + 0, // 59: ast.For.target:type_name -> ast.Node + 0, // 60: ast.For.iter:type_name -> ast.Node + 0, // 61: ast.For.body:type_name -> ast.Node + 6, // 62: ast.FunctionDef.Args:type_name -> ast.Arguments + 0, // 63: ast.FunctionDef.body:type_name -> ast.Node + 0, // 64: ast.FunctionDef.returns:type_name -> ast.Node + 0, // 65: ast.If.test:type_name -> ast.Node + 0, // 66: ast.If.body:type_name -> ast.Node + 0, // 67: ast.If.or_else:type_name -> ast.Node + 0, // 68: ast.Import.names:type_name -> ast.Node + 0, // 69: ast.ImportFrom.names:type_name -> ast.Node + 0, // 70: ast.ImportGroup.imports:type_name -> ast.Node + 0, // 71: ast.Keyword.value:type_name -> ast.Node + 0, // 72: ast.Module.body:type_name -> ast.Node + 0, // 73: ast.Return.value:type_name -> ast.Node + 26, // 74: ast.Subscript.value:type_name -> ast.Name + 0, // 75: ast.Subscript.slice:type_name -> ast.Node + 0, // 76: ast.Yield.value:type_name -> ast.Node + 77, // [77:77] is the sub-list for method output_type + 77, // [77:77] is the sub-list for method input_type + 77, // [77:77] is the sub-list for extension type_name + 77, // [77:77] is the sub-list for extension extendee + 0, // [0:77] is the sub-list for field type_name } func init() { file_ast_ast_proto_init() } diff --git a/internal/config.go b/internal/config.go index 009cb04..24009a2 100644 --- a/internal/config.go +++ b/internal/config.go @@ -1,12 +1,18 @@ package python +// TODO: Where are these properly documented? type Config struct { + EmitAsync bool `json:"emit_async"` // Emits async code instead of sync EmitExactTableNames bool `json:"emit_exact_table_names"` - EmitSyncQuerier bool `json:"emit_sync_querier"` - EmitAsyncQuerier bool `json:"emit_async_querier"` - Package string `json:"package"` - Out string `json:"out"` + EmitGenerators bool `json:"emit_generators"` // Will we use generators or lists, defaults to false + EmitModule bool `json:"emit_module"` // If true emits functions in module, else wraps in a class. EmitPydanticModels bool `json:"emit_pydantic_models"` - QueryParameterLimit *int32 `json:"query_parameter_limit"` + EmitSyncQuerier bool `json:"emit_sync_querier"` // DEPRECATED ALIAS FOR: emit_type = 'class', emit_generators = True + EmitAsyncQuerier bool `json:"emit_async_querier"` // DEPRECATED ALIAS FOR: emit_type = 'class', emit_generators = True InflectionExcludeTableNames []string `json:"inflection_exclude_table_names"` + Out string `json:"out"` + OutputModelsFileName *string `json:"output_models_file_name,omitempty"` // Can be string or null to exclude generating models file + OutputQuerierFile bool `json:"output_querier_file,omitempty"` // Skips outputting queries + Package string `json:"package"` + QueryParameterLimit *int32 `json:"query_parameter_limit"` } diff --git a/internal/endtoend/endtoend_test.go b/internal/endtoend/endtoend_test.go index bd66c27..62c9a8e 100644 --- a/internal/endtoend/endtoend_test.go +++ b/internal/endtoend/endtoend_test.go @@ -100,8 +100,9 @@ func TestGenerate(t *testing.T) { cmd := exec.Command(sqlc, "diff") cmd.Dir = dir got, err := cmd.CombinedOutput() + // TODO: We are diffing patches! Does this make sense and what should we provide to the end user? if diff := cmp.Diff(string(want), string(got)); diff != "" { - t.Errorf("sqlc diff mismatch (-want +got):\n%s", diff) + t.Errorf("sqlc diff mismatch (-want +got):\n%s", string(got)) } if len(want) == 0 && err != nil { t.Error(err) diff --git a/internal/endtoend/testdata/emit_pydantic_models/sqlc.yaml b/internal/endtoend/testdata/emit_pydantic_models/sqlc.yaml index 180ce29..d879adf 100644 --- a/internal/endtoend/testdata/emit_pydantic_models/sqlc.yaml +++ b/internal/endtoend/testdata/emit_pydantic_models/sqlc.yaml @@ -3,7 +3,7 @@ plugins: - name: py wasm: url: file://../../../../bin/sqlc-gen-python.wasm - sha256: "a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e" + sha256: "c97fad53818679a948c68f3ffe84530d7ca4999f636d3f3d89202c6c08ee224d" sql: - schema: schema.sql queries: query.sql diff --git a/internal/endtoend/testdata/exec_result/sqlc.yaml b/internal/endtoend/testdata/exec_result/sqlc.yaml index 2adbd31..b097b32 100644 --- a/internal/endtoend/testdata/exec_result/sqlc.yaml +++ b/internal/endtoend/testdata/exec_result/sqlc.yaml @@ -3,7 +3,7 @@ plugins: - name: py wasm: url: file://../../../../bin/sqlc-gen-python.wasm - sha256: "a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e" + sha256: "c97fad53818679a948c68f3ffe84530d7ca4999f636d3f3d89202c6c08ee224d" sql: - schema: schema.sql queries: query.sql diff --git a/internal/endtoend/testdata/exec_rows/sqlc.yaml b/internal/endtoend/testdata/exec_rows/sqlc.yaml index 2adbd31..b097b32 100644 --- a/internal/endtoend/testdata/exec_rows/sqlc.yaml +++ b/internal/endtoend/testdata/exec_rows/sqlc.yaml @@ -3,7 +3,7 @@ plugins: - name: py wasm: url: file://../../../../bin/sqlc-gen-python.wasm - sha256: "a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e" + sha256: "c97fad53818679a948c68f3ffe84530d7ca4999f636d3f3d89202c6c08ee224d" sql: - schema: schema.sql queries: query.sql diff --git a/internal/endtoend/testdata/inflection_exclude_table_names/sqlc.yaml b/internal/endtoend/testdata/inflection_exclude_table_names/sqlc.yaml index aba5400..7659ffe 100644 --- a/internal/endtoend/testdata/inflection_exclude_table_names/sqlc.yaml +++ b/internal/endtoend/testdata/inflection_exclude_table_names/sqlc.yaml @@ -3,7 +3,7 @@ plugins: - name: py wasm: url: file://../../../../bin/sqlc-gen-python.wasm - sha256: "a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e" + sha256: "c97fad53818679a948c68f3ffe84530d7ca4999f636d3f3d89202c6c08ee224d" sql: - schema: schema.sql queries: query.sql diff --git a/internal/endtoend/testdata/query_parameter_limit_two/sqlc.yaml b/internal/endtoend/testdata/query_parameter_limit_two/sqlc.yaml index e389988..961d105 100644 --- a/internal/endtoend/testdata/query_parameter_limit_two/sqlc.yaml +++ b/internal/endtoend/testdata/query_parameter_limit_two/sqlc.yaml @@ -3,7 +3,7 @@ plugins: - name: py wasm: url: file://../../../../bin/sqlc-gen-python.wasm - sha256: "a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e" + sha256: "c97fad53818679a948c68f3ffe84530d7ca4999f636d3f3d89202c6c08ee224d" sql: - schema: schema.sql queries: query.sql diff --git a/internal/endtoend/testdata/query_parameter_limit_undefined/sqlc.yaml b/internal/endtoend/testdata/query_parameter_limit_undefined/sqlc.yaml index 66d7a14..9bea901 100644 --- a/internal/endtoend/testdata/query_parameter_limit_undefined/sqlc.yaml +++ b/internal/endtoend/testdata/query_parameter_limit_undefined/sqlc.yaml @@ -3,7 +3,7 @@ plugins: - name: py wasm: url: file://../../../../bin/sqlc-gen-python.wasm - sha256: "a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e" + sha256: "c97fad53818679a948c68f3ffe84530d7ca4999f636d3f3d89202c6c08ee224d" sql: - schema: schema.sql queries: query.sql diff --git a/internal/endtoend/testdata/query_parameter_limit_zero/sqlc.yaml b/internal/endtoend/testdata/query_parameter_limit_zero/sqlc.yaml index 274f730..6f3bb75 100644 --- a/internal/endtoend/testdata/query_parameter_limit_zero/sqlc.yaml +++ b/internal/endtoend/testdata/query_parameter_limit_zero/sqlc.yaml @@ -3,7 +3,7 @@ plugins: - name: py wasm: url: file://../../../../bin/sqlc-gen-python.wasm - sha256: "a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e" + sha256: "c97fad53818679a948c68f3ffe84530d7ca4999f636d3f3d89202c6c08ee224d" sql: - schema: schema.sql queries: query.sql diff --git a/internal/endtoend/testdata/query_parameter_no_limit/sqlc.yaml b/internal/endtoend/testdata/query_parameter_no_limit/sqlc.yaml index b563730..d5c4da5 100644 --- a/internal/endtoend/testdata/query_parameter_no_limit/sqlc.yaml +++ b/internal/endtoend/testdata/query_parameter_no_limit/sqlc.yaml @@ -3,7 +3,7 @@ plugins: - name: py wasm: url: file://../../../../bin/sqlc-gen-python.wasm - sha256: "a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e" + sha256: "c97fad53818679a948c68f3ffe84530d7ca4999f636d3f3d89202c6c08ee224d" sql: - schema: schema.sql queries: query.sql diff --git a/internal/gen.go b/internal/gen.go index f81c53b..d9ae54d 100644 --- a/internal/gen.go +++ b/internal/gen.go @@ -53,6 +53,8 @@ type Field struct { Name string Type pyType Comment string + // EmbedFields contains the embedded fields that require scanning. + EmbedFields []Field } type Struct struct { @@ -105,14 +107,42 @@ func (v QueryValue) RowNode(rowVar string) *pyast.Node { call := &pyast.Call{ Func: v.Annotation(), } - for i, f := range v.Struct.Fields { - call.Keywords = append(call.Keywords, &pyast.Keyword{ - Arg: f.Name, - Value: subscriptNode( + rowIndex := 0 // We need to keep track of the index in the row variable. + for _, f := range v.Struct.Fields { + + var valueNode *pyast.Node + // Check if we are using sqlc.embed, if so we need to create a new object. + if len(f.EmbedFields) > 0 { + // We keep this separate so we can easily add all arguments. + embed_call := &pyast.Call{Func: f.Type.Annotation()} + + // Now add all field Initializers for the embedded model that index into the original row. + for i, embedField := range f.EmbedFields { + embed_call.Keywords = append(embed_call.Keywords, &pyast.Keyword{ + Arg: embedField.Name, + Value: subscriptNode( + rowVar, + constantInt(rowIndex+i), + ), + }) + } + + valueNode = &pyast.Node{ + Node: &pyast.Node_Call{ + Call: embed_call, + }, + } + + rowIndex += len(f.EmbedFields) + } else { + valueNode = subscriptNode( rowVar, - constantInt(i), - ), - }) + constantInt(rowIndex), + ) + rowIndex++ + } + + call.Keywords = append(call.Keywords, &pyast.Keyword{Arg: f.Name, Value: valueNode}) } return &pyast.Node{ Node: &pyast.Node_Call{ @@ -319,6 +349,47 @@ func paramName(p *plugin.Parameter) string { type pyColumn struct { id int32 *plugin.Column + embed *pyEmbed +} + +type pyEmbed struct { + modelType string + modelName string + fields []Field +} + +// Taken from https://github.com/sqlc-dev/sqlc/blob/8c59fbb9938a0bad3d9971fc2c10ea1f83cc1d0b/internal/codegen/golang/result.go#L123-L126 +// look through all the structs and attempt to find a matching one to embed +// We need the name of the struct and its field names. +func newGoEmbed(embed *plugin.Identifier, structs []Struct, defaultSchema string) *pyEmbed { + if embed == nil { + return nil + } + + for _, s := range structs { + embedSchema := defaultSchema + if embed.Schema != "" { + embedSchema = embed.Schema + } + + // compare the other attributes + if embed.Catalog != s.Table.Catalog || embed.Name != s.Table.Name || embedSchema != s.Table.Schema { + continue + } + + fields := make([]Field, len(s.Fields)) + for i, f := range s.Fields { + fields[i] = f + } + + return &pyEmbed{ + modelType: s.Name, + modelName: s.Name, + fields: fields, + } + } + + return nil } func columnsToStruct(req *plugin.GenerateRequest, name string, columns []pyColumn) *Struct { @@ -342,10 +413,22 @@ func columnsToStruct(req *plugin.GenerateRequest, name string, columns []pyColum if suffix > 0 { fieldName = fmt.Sprintf("%s_%d", fieldName, suffix) } - gs.Fields = append(gs.Fields, Field{ + + f := Field{ Name: fieldName, Type: makePyType(req, c.Column), - }) + } + + if c.embed != nil { + f.Type = pyType{ + InnerType: "models." + modelName(c.embed.modelType, req.Settings), + IsArray: false, + IsNull: false, + } + f.EmbedFields = c.embed.fields + } + + gs.Fields = append(gs.Fields, f) seen[colName]++ } return &gs @@ -459,6 +542,7 @@ func buildQueries(conf Config, req *plugin.GenerateRequest, structs []Struct) ([ columns = append(columns, pyColumn{ id: int32(i), Column: c, + embed: newGoEmbed(c.EmbedTable, structs, req.Catalog.DefaultSchema), }) } gs = columnsToStruct(req, query.Name+"Row", columns) @@ -601,12 +685,22 @@ func pydanticNode(name string) *pyast.ClassDef { } } -func fieldNode(f Field) *pyast.Node { +func fieldNode(f Field, defaultNone bool) *pyast.Node { + var value *pyast.Node = nil + if defaultNone && f.Type.IsNull { + value = &pyast.Node{ + Node: &pyast.Node_Name{ + Name: &pyast.Name{Id: "None"}, + }, + } + } + return &pyast.Node{ Node: &pyast.Node_AnnAssign{ AnnAssign: &pyast.AnnAssign{ Target: &pyast.Name{Id: f.Name}, Annotation: f.Type.Annotation(), + Value: value, Comment: f.Comment, }, }, @@ -621,7 +715,7 @@ func typeRefNode(base string, parts ...string) *pyast.Node { return n } -func connMethodNode(method, name string, arg *pyast.Node) *pyast.Node { +func connMethodNode(method *pyast.Node, name string, arg *pyast.Node) *pyast.Node { args := []*pyast.Node{ { Node: &pyast.Node_Call{ @@ -640,7 +734,7 @@ func connMethodNode(method, name string, arg *pyast.Node) *pyast.Node { return &pyast.Node{ Node: &pyast.Node_Call{ Call: &pyast.Call{ - Func: typeRefNode("self", "_conn", method), + Func: method, Args: args, }, }, @@ -724,7 +818,7 @@ func buildModelsTree(ctx *pyTmplCtx, i *importer) *pyast.Node { }) } for _, f := range m.Fields { - def.Body = append(def.Body, fieldNode(f)) + def.Body = append(def.Body, fieldNode(f, false)) } mod.Body = append(mod.Body, &pyast.Node{ Node: &pyast.Node_ClassDef{ @@ -736,9 +830,9 @@ func buildModelsTree(ctx *pyTmplCtx, i *importer) *pyast.Node { return &pyast.Node{Node: &pyast.Node_Module{Module: mod}} } -func querierClassDef() *pyast.ClassDef { +func querierClassDef(name string, connectionAnnotation *pyast.Node) *pyast.ClassDef { return &pyast.ClassDef{ - Name: "Querier", + Name: name, Body: []*pyast.Node{ { Node: &pyast.Node_FunctionDef{ @@ -751,7 +845,7 @@ func querierClassDef() *pyast.ClassDef { }, { Arg: "conn", - Annotation: typeRefNode("sqlalchemy", "engine", "Connection"), + Annotation: connectionAnnotation, }, }, }, @@ -774,42 +868,177 @@ func querierClassDef() *pyast.ClassDef { } } -func asyncQuerierClassDef() *pyast.ClassDef { - return &pyast.ClassDef{ - Name: "AsyncQuerier", - Body: []*pyast.Node{ - { - Node: &pyast.Node_FunctionDef{ - FunctionDef: &pyast.FunctionDef{ - Name: "__init__", - Args: &pyast.Arguments{ - Args: []*pyast.Arg{ - { - Arg: "self", +func buildQuerierClass(ctx *pyTmplCtx, isAsync bool) []*pyast.Node { + functions := make([]*pyast.Node, 0, 10) + + // Define some reused types based on async or sync code + var connectionAnnotation *pyast.Node + if isAsync { + connectionAnnotation = typeRefNode("sqlalchemy", "ext", "asyncio", "AsyncConnection") + } else { + connectionAnnotation = typeRefNode("sqlalchemy", "engine", "Connection") + } + + // We need to figure out how to access the SQLAlchemy connectionVar object + var connectionVar *pyast.Node + if ctx.C.EmitModule { + connectionVar = poet.Name("conn") + } else { + connectionVar = poet.Attribute(poet.Name("self"), "_conn") + } + + // We loop through all queries and build our query functions + for _, q := range ctx.Queries { + if !ctx.OutputQuery(q.SourceName) { + continue + } + f := &pyast.FunctionDef{ + Name: q.MethodName, + Args: &pyast.Arguments{}, + } + + if ctx.C.EmitModule { + f.Args.Args = append(f.Args.Args, &pyast.Arg{ + Arg: "conn", + Annotation: connectionAnnotation, + }) + } else { + f.Args.Args = append(f.Args.Args, &pyast.Arg{ + Arg: "self", + }) + } + + q.AddArgs(f.Args) + + exec := poet.Expr(connMethodNode(poet.Attribute(connectionVar, "execute"), q.ConstantName, q.ArgDictNode())) + if isAsync { + exec = poet.Await(exec) + } + + switch q.Cmd { + case ":one": + f.Body = append(f.Body, + assignNode("row", poet.Node( + &pyast.Call{ + Func: poet.Attribute(exec, "first"), + }, + )), + poet.Node( + &pyast.If{ + Test: poet.Node( + &pyast.Compare{ + Left: poet.Name("row"), + Ops: []*pyast.Node{ + poet.Is(), }, - { - Arg: "conn", - Annotation: typeRefNode("sqlalchemy", "ext", "asyncio", "AsyncConnection"), + Comparators: []*pyast.Node{ + poet.Constant(nil), }, }, - }, + ), Body: []*pyast.Node{ - { - Node: &pyast.Node_Assign{ - Assign: &pyast.Assign{ - Targets: []*pyast.Node{ - poet.Attribute(poet.Name("self"), "_conn"), - }, - Value: poet.Name("conn"), - }, + poet.Return( + poet.Constant(nil), + ), + }, + }, + ), + poet.Return(q.Ret.RowNode("row")), + ) + f.Returns = subscriptNode("Optional", q.Ret.Annotation()) + case ":many": + if ctx.C.EmitGenerators { + if isAsync { + // If we are using generators and async, we are switching to stream implementation + exec = poet.Await(connMethodNode(poet.Attribute(connectionVar, "stream"), q.ConstantName, q.ArgDictNode())) + + f.Returns = subscriptNode("AsyncIterator", q.Ret.Annotation()) + f.Body = append(f.Body, + assignNode("result", exec), + poet.Node( + &pyast.AsyncFor{ + Target: poet.Name("row"), + Iter: poet.Name("result"), + Body: []*pyast.Node{ + poet.Expr( + poet.Yield( + q.Ret.RowNode("row"), + ), + ), }, }, + )) + } else { + f.Returns = subscriptNode("Iterator", q.Ret.Annotation()) + f.Body = append(f.Body, + assignNode("result", exec), + poet.Node( + &pyast.For{ + Target: poet.Name("row"), + Iter: poet.Name("result"), + Body: []*pyast.Node{ + poet.Expr( + poet.Yield( + q.Ret.RowNode("row"), + ), + ), + }, + }, + )) + } + } else { + f.Body = append(f.Body, + assignNode("result", poet.Node( + &pyast.Call{ + Func: poet.Attribute(exec, "all"), }, + )), + poet.Node(&pyast.Return{ + Value: poet.Node( + &pyast.For{ + Target: poet.Name("row"), + Iter: poet.Name("result"), + Body: []*pyast.Node{ + q.Ret.RowNode("row"), + }, + }, + ), }, - }, - }, - }, + )) + f.Returns = subscriptNode("List", q.Ret.Annotation()) + } + case ":exec": + f.Body = append(f.Body, exec) + f.Returns = poet.Constant(nil) + case ":execrows": + f.Body = append(f.Body, + assignNode("result", exec), + poet.Return(poet.Attribute(poet.Name("result"), "rowcount")), + ) + f.Returns = poet.Name("int") + case ":execresult": + f.Body = append(f.Body, + poet.Return(exec), + ) + f.Returns = typeRefNode("sqlalchemy", "engine", "Result") + default: + panic("unknown cmd " + q.Cmd) + } + + // If we are emitting async code, we have to swap our sync func for an async one and fix the conn annotation. + if isAsync { + functions = append(functions, poet.Node(&pyast.AsyncFunctionDef{ + Name: f.Name, + Args: f.Args, + Body: f.Body, + Returns: f.Returns, + })) + } else { + functions = append(functions, poet.Node(f)) + } } + + return functions } func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node { @@ -841,6 +1070,8 @@ func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node { } queryText := fmt.Sprintf("-- name: %s \\\\%s\n%s\n", q.MethodName, q.Cmd, q.SQL) mod.Body = append(mod.Body, assignNode(q.ConstantName, poet.Constant(queryText))) + + // Generate params structures for _, arg := range q.Args { if arg.EmitStruct() { var def *pyast.ClassDef @@ -849,8 +1080,18 @@ func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node { } else { def = dataclassNode(arg.Struct.Name) } - for _, f := range arg.Struct.Fields { - def.Body = append(def.Body, fieldNode(f)) + + // We need a copy as we want to make sure that nullable params are at the end of the dataclass + fields := make([]Field, len(arg.Struct.Fields)) + copy(fields, arg.Struct.Fields) + + // Place all nullable fields at the end and try to keep the original order as much as possible + sort.SliceStable(fields, func(i int, j int) bool { + return (fields[j].Type.IsNull && fields[i].Type.IsNull != fields[j].Type.IsNull) || i < j + }) + + for _, f := range fields { + def.Body = append(def.Body, fieldNode(f, true)) } mod.Body = append(mod.Body, poet.Node(def)) } @@ -863,195 +1104,49 @@ func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node { def = dataclassNode(q.Ret.Struct.Name) } for _, f := range q.Ret.Struct.Fields { - def.Body = append(def.Body, fieldNode(f)) + def.Body = append(def.Body, fieldNode(f, false)) } mod.Body = append(mod.Body, poet.Node(def)) } } - if ctx.C.EmitSyncQuerier { - cls := querierClassDef() - for _, q := range ctx.Queries { - if !ctx.OutputQuery(q.SourceName) { - continue + // Lets see how to add all functions, we can either add them to the module directly or from within a class. + if ctx.C.EmitModule { + mod.Body = append(mod.Body, buildQuerierClass(ctx, ctx.C.EmitAsync)...) + } else { + asyncConnectionAnnotation := typeRefNode("sqlalchemy", "ext", "asyncio", "AsyncConnection") + syncConnectionAnnotation := typeRefNode("sqlalchemy", "engine", "Connection") + + // NOTE: For backwards compatibility we support generating multiple classes, but this is definitely suboptimal. + // It is much better to use the `emit_async: bool` config to select what type to emit + if ctx.C.EmitAsyncQuerier || ctx.C.EmitSyncQuerier { + + // When using these backwards compatible settings we force behavior! + ctx.C.EmitModule = false + ctx.C.EmitGenerators = true + + if ctx.C.EmitSyncQuerier { + cls := querierClassDef("Querier", syncConnectionAnnotation) + cls.Body = append(cls.Body, buildQuerierClass(ctx, false)...) + mod.Body = append(mod.Body, poet.Node(cls)) } - f := &pyast.FunctionDef{ - Name: q.MethodName, - Args: &pyast.Arguments{ - Args: []*pyast.Arg{ - { - Arg: "self", - }, - }, - }, + if ctx.C.EmitAsyncQuerier { + cls := querierClassDef("AsyncQuerier", asyncConnectionAnnotation) + cls.Body = append(cls.Body, buildQuerierClass(ctx, true)...) + mod.Body = append(mod.Body, poet.Node(cls)) } - - q.AddArgs(f.Args) - exec := connMethodNode("execute", q.ConstantName, q.ArgDictNode()) - - switch q.Cmd { - case ":one": - f.Body = append(f.Body, - assignNode("row", poet.Node( - &pyast.Call{ - Func: poet.Attribute(exec, "first"), - }, - )), - poet.Node( - &pyast.If{ - Test: poet.Node( - &pyast.Compare{ - Left: poet.Name("row"), - Ops: []*pyast.Node{ - poet.Is(), - }, - Comparators: []*pyast.Node{ - poet.Constant(nil), - }, - }, - ), - Body: []*pyast.Node{ - poet.Return( - poet.Constant(nil), - ), - }, - }, - ), - poet.Return(q.Ret.RowNode("row")), - ) - f.Returns = subscriptNode("Optional", q.Ret.Annotation()) - case ":many": - f.Body = append(f.Body, - assignNode("result", exec), - poet.Node( - &pyast.For{ - Target: poet.Name("row"), - Iter: poet.Name("result"), - Body: []*pyast.Node{ - poet.Expr( - poet.Yield( - q.Ret.RowNode("row"), - ), - ), - }, - }, - ), - ) - f.Returns = subscriptNode("Iterator", q.Ret.Annotation()) - case ":exec": - f.Body = append(f.Body, exec) - f.Returns = poet.Constant(nil) - case ":execrows": - f.Body = append(f.Body, - assignNode("result", exec), - poet.Return(poet.Attribute(poet.Name("result"), "rowcount")), - ) - f.Returns = poet.Name("int") - case ":execresult": - f.Body = append(f.Body, - poet.Return(exec), - ) - f.Returns = typeRefNode("sqlalchemy", "engine", "Result") - default: - panic("unknown cmd " + q.Cmd) - } - - cls.Body = append(cls.Body, poet.Node(f)) - } - mod.Body = append(mod.Body, poet.Node(cls)) - } - - if ctx.C.EmitAsyncQuerier { - cls := asyncQuerierClassDef() - for _, q := range ctx.Queries { - if !ctx.OutputQuery(q.SourceName) { - continue - } - f := &pyast.AsyncFunctionDef{ - Name: q.MethodName, - Args: &pyast.Arguments{ - Args: []*pyast.Arg{ - { - Arg: "self", - }, - }, - }, - } - - q.AddArgs(f.Args) - exec := connMethodNode("execute", q.ConstantName, q.ArgDictNode()) - - switch q.Cmd { - case ":one": - f.Body = append(f.Body, - assignNode("row", poet.Node( - &pyast.Call{ - Func: poet.Attribute(poet.Await(exec), "first"), - }, - )), - poet.Node( - &pyast.If{ - Test: poet.Node( - &pyast.Compare{ - Left: poet.Name("row"), - Ops: []*pyast.Node{ - poet.Is(), - }, - Comparators: []*pyast.Node{ - poet.Constant(nil), - }, - }, - ), - Body: []*pyast.Node{ - poet.Return( - poet.Constant(nil), - ), - }, - }, - ), - poet.Return(q.Ret.RowNode("row")), - ) - f.Returns = subscriptNode("Optional", q.Ret.Annotation()) - case ":many": - stream := connMethodNode("stream", q.ConstantName, q.ArgDictNode()) - f.Body = append(f.Body, - assignNode("result", poet.Await(stream)), - poet.Node( - &pyast.AsyncFor{ - Target: poet.Name("row"), - Iter: poet.Name("result"), - Body: []*pyast.Node{ - poet.Expr( - poet.Yield( - q.Ret.RowNode("row"), - ), - ), - }, - }, - ), - ) - f.Returns = subscriptNode("AsyncIterator", q.Ret.Annotation()) - case ":exec": - f.Body = append(f.Body, poet.Await(exec)) - f.Returns = poet.Constant(nil) - case ":execrows": - f.Body = append(f.Body, - assignNode("result", poet.Await(exec)), - poet.Return(poet.Attribute(poet.Name("result"), "rowcount")), - ) - f.Returns = poet.Name("int") - case ":execresult": - f.Body = append(f.Body, - poet.Return(poet.Await(exec)), - ) - f.Returns = typeRefNode("sqlalchemy", "engine", "Result") - default: - panic("unknown cmd " + q.Cmd) + } else { + var connectionAnnotation *pyast.Node + if ctx.C.EmitAsync { + connectionAnnotation = asyncConnectionAnnotation + } else { + connectionAnnotation = syncConnectionAnnotation } - cls.Body = append(cls.Body, poet.Node(f)) + cls := querierClassDef("Querier", connectionAnnotation) + cls.Body = append(cls.Body, buildQuerierClass(ctx, ctx.C.EmitAsync)...) + mod.Body = append(mod.Body, poet.Node(cls)) } - mod.Body = append(mod.Body, poet.Node(cls)) } return poet.Node(mod) @@ -1075,7 +1170,13 @@ func HashComment(s string) string { } func Generate(_ context.Context, req *plugin.GenerateRequest) (*plugin.GenerateResponse, error) { - var conf Config + // Setup our defaults for our Config struct and parse our config file + defaultModelsFileName := "models.py" + conf := Config{ + OutputModelsFileName: &defaultModelsFileName, + OutputQuerierFile: true, + } + if len(req.PluginOptions) > 0 { if err := json.Unmarshal(req.PluginOptions, &conf); err != nil { return nil, err @@ -1105,26 +1206,34 @@ func Generate(_ context.Context, req *plugin.GenerateRequest) (*plugin.GenerateR } output := map[string]string{} - result := pyprint.Print(buildModelsTree(&tctx, i), pyprint.Options{}) - tctx.SourceName = "models.py" - output["models.py"] = string(result.Python) - files := map[string]struct{}{} - for _, q := range queries { - files[q.SourceName] = struct{}{} + // Generate the model file. + if conf.OutputModelsFileName != nil { + result := pyprint.Print(buildModelsTree(&tctx, i), pyprint.Options{}) + tctx.SourceName = *conf.OutputModelsFileName + output[*conf.OutputModelsFileName] = string(result.Python) } - for source := range files { - tctx.SourceName = source - result := pyprint.Print(buildQueryTree(&tctx, i, source), pyprint.Options{}) - name := source - if !strings.HasSuffix(name, ".py") { - name = strings.TrimSuffix(name, ".sql") - name += ".py" + // Generate for each .sql file a corresponding Python query file. + if conf.OutputQuerierFile { + files := map[string]struct{}{} + for _, q := range queries { + files[q.SourceName] = struct{}{} + } + + for source := range files { + tctx.SourceName = source + result := pyprint.Print(buildQueryTree(&tctx, i, source), pyprint.Options{}) + name := source + if !strings.HasSuffix(name, ".py") { + name = strings.TrimSuffix(name, ".sql") + name += ".py" + } + output[name] = string(result.Python) } - output[name] = string(result.Python) } + // Finally we send our outputs back to SQLC resp := plugin.GenerateResponse{} for filename, code := range output { diff --git a/internal/imports.go b/internal/imports.go index b88c58c..bf4da20 100644 --- a/internal/imports.go +++ b/internal/imports.go @@ -132,7 +132,7 @@ func (i *importer) queryImportSpecs(fileName string) (map[string]importSpec, map pkg := make(map[string]importSpec) pkg["sqlalchemy"] = importSpec{Module: "sqlalchemy"} - if i.C.EmitAsyncQuerier { + if i.C.EmitAsync || i.C.EmitAsyncQuerier { pkg["sqlalchemy.ext.asyncio"] = importSpec{Module: "sqlalchemy.ext.asyncio"} } @@ -154,11 +154,16 @@ func (i *importer) queryImportSpecs(fileName string) (map[string]importSpec, map std["typing.Optional"] = importSpec{Module: "typing", Name: "Optional"} } if q.Cmd == ":many" { - if i.C.EmitSyncQuerier { - std["typing.Iterator"] = importSpec{Module: "typing", Name: "Iterator"} - } - if i.C.EmitAsyncQuerier { - std["typing.AsyncIterator"] = importSpec{Module: "typing", Name: "AsyncIterator"} + // NOTE: We are adding backwards compatible behavior + if i.C.EmitGenerators || i.C.EmitSyncQuerier || i.C.EmitAsyncQuerier { + if i.C.EmitAsync || i.C.EmitAsyncQuerier { + std["typing.AsyncIterator"] = importSpec{Module: "typing", Name: "AsyncIterator"} + } + if !i.C.EmitAsync || i.C.EmitSyncQuerier { + std["typing.Iterator"] = importSpec{Module: "typing", Name: "Iterator"} + } + } else { + std["typing.List"] = importSpec{Module: "typing", Name: "List"} } } queryValueModelImports(q.Ret) diff --git a/internal/poet/poet.go b/internal/poet/poet.go index 22b488c..fc22995 100644 --- a/internal/poet/poet.go +++ b/internal/poet/poet.go @@ -161,6 +161,13 @@ func Node(node proto) *ast.Node { // case *ast.Node_Subscript: // w.printSubscript(n.Subscript, indent) + case *ast.Return: + return &ast.Node{ + Node: &ast.Node_Return{ + Return: n, + }, + } + case *ast.Yield: return &ast.Node{ Node: &ast.Node_Yield{ diff --git a/internal/postgresql_type.go b/internal/postgresql_type.go index 3d0891b..6d798cb 100644 --- a/internal/postgresql_type.go +++ b/internal/postgresql_type.go @@ -22,7 +22,7 @@ func postgresType(req *plugin.GenerateRequest, col *plugin.Column) string { case "json", "jsonb": return "Any" case "bytea", "blob", "pg_catalog.bytea": - return "memoryview" + return "bytes" case "date": return "datetime.date" case "pg_catalog.time", "pg_catalog.timetz": diff --git a/internal/printer/printer.go b/internal/printer/printer.go index 0660c6a..b761b54 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -83,7 +83,7 @@ func (w *writer) printNode(node *ast.Node, indent int32) { w.printNode(n.Expr.Value, indent) case *ast.Node_For: - w.printFor(n.For, indent) + w.printFor(n.For, false, indent) case *ast.Node_FunctionDef: w.printFunctionDef(n.FunctionDef, indent) @@ -140,6 +140,10 @@ func (w *writer) printAnnAssign(aa *ast.AnnAssign, indent int32) { w.printName(aa.Target, indent) w.print(": ") w.printNode(aa.Annotation, indent) + if aa.Value != nil { + w.print(" = ") + w.printNode(aa.Value, indent) + } } func (w *writer) printArg(a *ast.Arg, indent int32) { @@ -162,12 +166,11 @@ func (w *writer) printAssign(a *ast.Assign, indent int32) { } func (w *writer) printAsyncFor(n *ast.AsyncFor, indent int32) { - w.print("async ") w.printFor(&ast.For{ Target: n.Target, Iter: n.Iter, Body: n.Body, - }, indent) + }, true, indent) } func (w *writer) printAsyncFunctionDef(afd *ast.AsyncFunctionDef, indent int32) { @@ -341,17 +344,45 @@ func (w *writer) printDict(d *ast.Dict, indent int32) { w.print("}") } -func (w *writer) printFor(n *ast.For, indent int32) { - w.print("for ") - w.printNode(n.Target, indent) - w.print(" in ") - w.printNode(n.Iter, indent) - w.print(":\n") - for i, node := range n.Body { +func (w *writer) printFor(n *ast.For, isAsync bool, indent int32) { + // We should always have a body + if len(n.Body) <= 0 { + panic(n) + } + + // TODO: How to better support list comprehension? Maybe add a flag to AST node ForNode and AsyncNode? + _, isCall := n.Body[0].Node.(*ast.Node_Call) + if len(n.Body) == 1 && isCall { + w.print("[\n") w.printIndent(indent + 1) - w.printNode(node, indent+1) - if i != len(n.Body)-1 { - w.print("\n") + w.printNode(n.Body[0], indent+1) + w.print("\n") + w.printIndent(indent + 1) + if isAsync { + w.print("async ") + } + w.print("for ") + w.printNode(n.Target, indent) + w.print(" in ") + w.printNode(n.Iter, indent) + w.print("\n") + w.printIndent(indent) + w.print("]\n") + } else { + if isAsync { + w.print("async ") + } + w.print("for ") + w.printNode(n.Target, indent) + w.print(" in ") + w.printNode(n.Iter, indent) + w.print(":\n") + for i, node := range n.Body { + w.printIndent(indent + 1) + w.printNode(node, indent+1) + if i != len(n.Body)-1 { + w.print("\n") + } } } } @@ -455,14 +486,20 @@ func (w *writer) printModule(mod *ast.Module, indent int32) { _, isImport := mod.Body[i-1].Node.(*ast.Node_ImportGroup) prevIsImport = isImport } + _, isClassDef := node.Node.(*ast.Node_ClassDef) + _, isFunctionDef := node.Node.(*ast.Node_FunctionDef) + _, isAsyncFunctionDef := node.Node.(*ast.Node_AsyncFunctionDef) _, isAssign := node.Node.(*ast.Node_Assign) + if isClassDef || isAssign { if prevIsImport { w.print("\n") } else { w.print("\n\n") } + } else if isAsyncFunctionDef || isFunctionDef { + w.print("\n\n\n") } w.printNode(node, indent) if isAssign { diff --git a/protos/ast/ast.proto b/protos/ast/ast.proto index a8daa62..4188f36 100644 --- a/protos/ast/ast.proto +++ b/protos/ast/ast.proto @@ -59,8 +59,9 @@ 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"]; + Node value = 3 [json_name="value"]; + int32 simple = 4 [json_name="simple"]; + string Comment = 5 [json_name="comment"]; } message Arg