diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 39d10da1..26cc111d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,19 +35,17 @@ Twirp uses github pull requests. Fork, hack away at your changes and submit. Mos * Add tests that cover your contribution. Overall code coverage should not decrease. * Twirp officially supports the last 3 releases of Go. * Protobuf version 3.x.x to generate code with the protoc command. - * The Python implementation uses Python 2.7. As such, it is not suitable for production use in its current form. * For linters and other tools, we use [retool](https://github.com/twitchtv/retool). If `make setup` is not able to install it, you can install it in your path with `go get github.com/twitchtv/retool` and then install tools with `retool build`. ### Running tests Generally you want to make changes and run `make`, which will install all -dependencies we know about, build the core, and run all of the tests that we -have against Go and Python code. A few notes: +dependencies we know about, build the core, and run tests. A few notes: * Clone the repo on `$GOPATH/src/github.com/twitchtv/twirp` (go modules not supported yet). * Run Go unit tests with `make test`. * Most tests of the Go server are in `internal/twirptest/service_test.go`. - * Integration tests running the full stack in both Go and Python auto-generated clients are in the [clientcompat](./clientcompat) directory. + * Integration tests running the full stack in Go are in the [clientcompat](./clientcompat) directory. ## Contributing Documentation diff --git a/Makefile b/Makefile index 84629aca..420ec8a5 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ export GO111MODULE=off all: setup test_all -.PHONY: setup generate test_all test test_clients test_go_client test_python_client +.PHONY: setup generate test_all test test_clientcompat setup: ./check_protoc_version.sh @@ -13,26 +13,18 @@ setup: generate: # Recompile and install generator GOBIN="$$PWD/bin" go install -v ./protoc-gen-twirp - GOBIN="$$PWD/bin" go install -v ./protoc-gen-twirp_python # Generate code from go:generate comments go generate ./... -test_all: setup test test_clients +test_all: setup test test_clientcompat test: generate ./_tools/bin/errcheck ./internal/twirptest go test -race $(shell GO111MODULE=off go list ./... | grep -v /vendor/ | grep -v /_tools/) -test_clients: test_go_client test_python_client - -test_go_client: generate build/clientcompat build/gocompat +test_clientcompat: generate build/clientcompat build/gocompat ./build/clientcompat -client ./build/gocompat -test_python_client: generate build/clientcompat build/pycompat - ./build/clientcompat -client ./build/pycompat - - -# For clientcompat and testing Python ./build: mkdir build @@ -41,13 +33,3 @@ test_python_client: generate build/clientcompat build/pycompat ./build/clientcompat: ./build go build -o build/clientcompat ./clientcompat - -./build/venv: ./build - virtualenv ./build/venv - -./build/venv/bin/pycompat.py: ./build/venv - ./build/venv/bin/pip install --upgrade ./clientcompat/pycompat - -./build/pycompat: ./build/venv/bin/pycompat.py - cp ./clientcompat/pycompat/pycompat.sh ./build/pycompat - chmod +x ./build/pycompat diff --git a/clientcompat/gen.go b/clientcompat/gen.go index 6f36f1c8..a09ff0d3 100644 --- a/clientcompat/gen.go +++ b/clientcompat/gen.go @@ -14,4 +14,3 @@ package main //go:generate protoc --twirp_out=. --go_out=. clientcompat.proto -//go:generate protoc --twirp_python_out=./pycompat --python_out=./pycompat clientcompat.proto diff --git a/clientcompat/pycompat/clientcompat_pb2.py b/clientcompat/pycompat/clientcompat_pb2.py deleted file mode 100644 index 7f9ecb20..00000000 --- a/clientcompat/pycompat/clientcompat_pb2.py +++ /dev/null @@ -1,262 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: clientcompat.proto -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor.FileDescriptor( - name='clientcompat.proto', - package='twirp.clientcompat', - syntax='proto3', - serialized_options=b'Z\026/internal/clientcompat', - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x12\x63lientcompat.proto\x12\x12twirp.clientcompat\"\x07\n\x05\x45mpty\"\x10\n\x03Req\x12\t\n\x01v\x18\x01 \x01(\t\"\x11\n\x04Resp\x12\t\n\x01v\x18\x01 \x01(\x05\"\xb9\x01\n\x13\x43lientCompatMessage\x12\x17\n\x0fservice_address\x18\x01 \x01(\t\x12K\n\x06method\x18\x02 \x01(\x0e\x32;.twirp.clientcompat.ClientCompatMessage.CompatServiceMethod\x12\x0f\n\x07request\x18\x03 \x01(\x0c\"+\n\x13\x43ompatServiceMethod\x12\x08\n\x04NOOP\x10\x00\x12\n\n\x06METHOD\x10\x01\x32\x90\x01\n\rCompatService\x12;\n\x06Method\x12\x17.twirp.clientcompat.Req\x1a\x18.twirp.clientcompat.Resp\x12\x42\n\nNoopMethod\x12\x19.twirp.clientcompat.Empty\x1a\x19.twirp.clientcompat.EmptyB\x18Z\x16/internal/clientcompatb\x06proto3' -) - - - -_CLIENTCOMPATMESSAGE_COMPATSERVICEMETHOD = _descriptor.EnumDescriptor( - name='CompatServiceMethod', - full_name='twirp.clientcompat.ClientCompatMessage.CompatServiceMethod', - filename=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - values=[ - _descriptor.EnumValueDescriptor( - name='NOOP', index=0, number=0, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='METHOD', index=1, number=1, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - ], - containing_type=None, - serialized_options=None, - serialized_start=231, - serialized_end=274, -) -_sym_db.RegisterEnumDescriptor(_CLIENTCOMPATMESSAGE_COMPATSERVICEMETHOD) - - -_EMPTY = _descriptor.Descriptor( - name='Empty', - full_name='twirp.clientcompat.Empty', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=42, - serialized_end=49, -) - - -_REQ = _descriptor.Descriptor( - name='Req', - full_name='twirp.clientcompat.Req', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='v', full_name='twirp.clientcompat.Req.v', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=51, - serialized_end=67, -) - - -_RESP = _descriptor.Descriptor( - name='Resp', - full_name='twirp.clientcompat.Resp', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='v', full_name='twirp.clientcompat.Resp.v', index=0, - number=1, type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=69, - serialized_end=86, -) - - -_CLIENTCOMPATMESSAGE = _descriptor.Descriptor( - name='ClientCompatMessage', - full_name='twirp.clientcompat.ClientCompatMessage', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='service_address', full_name='twirp.clientcompat.ClientCompatMessage.service_address', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='method', full_name='twirp.clientcompat.ClientCompatMessage.method', index=1, - number=2, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='request', full_name='twirp.clientcompat.ClientCompatMessage.request', index=2, - number=3, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=b"", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - _CLIENTCOMPATMESSAGE_COMPATSERVICEMETHOD, - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=89, - serialized_end=274, -) - -_CLIENTCOMPATMESSAGE.fields_by_name['method'].enum_type = _CLIENTCOMPATMESSAGE_COMPATSERVICEMETHOD -_CLIENTCOMPATMESSAGE_COMPATSERVICEMETHOD.containing_type = _CLIENTCOMPATMESSAGE -DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY -DESCRIPTOR.message_types_by_name['Req'] = _REQ -DESCRIPTOR.message_types_by_name['Resp'] = _RESP -DESCRIPTOR.message_types_by_name['ClientCompatMessage'] = _CLIENTCOMPATMESSAGE -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), { - 'DESCRIPTOR' : _EMPTY, - '__module__' : 'clientcompat_pb2' - # @@protoc_insertion_point(class_scope:twirp.clientcompat.Empty) - }) -_sym_db.RegisterMessage(Empty) - -Req = _reflection.GeneratedProtocolMessageType('Req', (_message.Message,), { - 'DESCRIPTOR' : _REQ, - '__module__' : 'clientcompat_pb2' - # @@protoc_insertion_point(class_scope:twirp.clientcompat.Req) - }) -_sym_db.RegisterMessage(Req) - -Resp = _reflection.GeneratedProtocolMessageType('Resp', (_message.Message,), { - 'DESCRIPTOR' : _RESP, - '__module__' : 'clientcompat_pb2' - # @@protoc_insertion_point(class_scope:twirp.clientcompat.Resp) - }) -_sym_db.RegisterMessage(Resp) - -ClientCompatMessage = _reflection.GeneratedProtocolMessageType('ClientCompatMessage', (_message.Message,), { - 'DESCRIPTOR' : _CLIENTCOMPATMESSAGE, - '__module__' : 'clientcompat_pb2' - # @@protoc_insertion_point(class_scope:twirp.clientcompat.ClientCompatMessage) - }) -_sym_db.RegisterMessage(ClientCompatMessage) - - -DESCRIPTOR._options = None - -_COMPATSERVICE = _descriptor.ServiceDescriptor( - name='CompatService', - full_name='twirp.clientcompat.CompatService', - file=DESCRIPTOR, - index=0, - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_start=277, - serialized_end=421, - methods=[ - _descriptor.MethodDescriptor( - name='Method', - full_name='twirp.clientcompat.CompatService.Method', - index=0, - containing_service=None, - input_type=_REQ, - output_type=_RESP, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='NoopMethod', - full_name='twirp.clientcompat.CompatService.NoopMethod', - index=1, - containing_service=None, - input_type=_EMPTY, - output_type=_EMPTY, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), -]) -_sym_db.RegisterServiceDescriptor(_COMPATSERVICE) - -DESCRIPTOR.services_by_name['CompatService'] = _COMPATSERVICE - -# @@protoc_insertion_point(module_scope) diff --git a/clientcompat/pycompat/clientcompat_pb2_twirp.py b/clientcompat/pycompat/clientcompat_pb2_twirp.py deleted file mode 100644 index 8c274515..00000000 --- a/clientcompat/pycompat/clientcompat_pb2_twirp.py +++ /dev/null @@ -1,85 +0,0 @@ -# Code generated by protoc-gen-twirp_python v8.0.0, DO NOT EDIT. -# source: clientcompat.proto - -try: - import httplib - from urllib2 import Request, HTTPError, urlopen -except ImportError: - import http.client as httplib - from urllib.request import Request, urlopen - from urllib.error import HTTPError -import json -from google.protobuf import symbol_database as _symbol_database -import sys - -_sym_db = _symbol_database.Default() - -class TwirpException(httplib.HTTPException): - def __init__(self, code, message, meta): - self.code = code - self.message = message - self.meta = meta - super(TwirpException, self).__init__(message) - - @classmethod - def from_http_err(cls, err): - try: - jsonerr = json.load(err) - code = jsonerr["code"] - msg = jsonerr["msg"] - meta = jsonerr.get("meta") - if meta is None: - meta = {} - except: - code = "internal" - msg = "Error from intermediary with HTTP status code {} {}".format( - err.code, httplib.responses[err.code], - ) - meta = {} - return cls(code, msg, meta) - -class CompatServiceClient(object): - def __init__(self, server_address): - """Creates a new client for the CompatService service. - - Args: - server_address: The address of the server to send requests to, in - the full protocol://host:port form. - """ - if sys.version_info[0] > 2: - self.__target = server_address - else: - self.__target = server_address.encode('ascii') - self.__service_name = "twirp.clientcompat.CompatService" - - def __make_request(self, body, full_method): - req = Request( - url=self.__target + "/twirp" + full_method, - data=body, - headers={"Content-Type": "application/protobuf"}, - ) - try: - resp = urlopen(req) - except HTTPError as err: - raise TwirpException.from_http_err(err) - - return resp.read() - - def method(self, req): - serialize = _sym_db.GetSymbol("twirp.clientcompat.Req").SerializeToString - deserialize = _sym_db.GetSymbol("twirp.clientcompat.Resp").FromString - - full_method = "/{}/{}".format(self.__service_name, "Method") - body = serialize(req) - resp_str = self.__make_request(body=body, full_method=full_method) - return deserialize(resp_str) - - def noop_method(self, empty): - serialize = _sym_db.GetSymbol("twirp.clientcompat.Empty").SerializeToString - deserialize = _sym_db.GetSymbol("twirp.clientcompat.Empty").FromString - - full_method = "/{}/{}".format(self.__service_name, "NoopMethod") - body = serialize(empty) - resp_str = self.__make_request(body=body, full_method=full_method) - return deserialize(resp_str) - diff --git a/clientcompat/pycompat/pycompat.py b/clientcompat/pycompat/pycompat.py deleted file mode 100755 index 49876185..00000000 --- a/clientcompat/pycompat/pycompat.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You may not -# use this file except in compliance with the License. A copy of the License is -# located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the "license" file accompanying this file. This file is distributed on -# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -# express or implied. See the License for the specific language governing -# permissions and limitations under the License. - -from __future__ import print_function - -import sys - -import clientcompat_pb2 -import clientcompat_pb2_twirp - -def main(): - req = read_request() - client = clientcompat_pb2_twirp.CompatServiceClient(req.service_address) - try: - resp = do_request(client, req) - sys.stdout.write(resp.SerializeToString().decode(encoding="utf-8")) - except clientcompat_pb2_twirp.TwirpException as e: - sys.stderr.write(e.code) - - -def read_request(): - input_str = sys.stdin.read() - return clientcompat_pb2.ClientCompatMessage.FromString(input_str.encode(encoding="utf-8")) - - -def do_request(client, req): - if req.method == clientcompat_pb2.ClientCompatMessage.NOOP: - input_type = clientcompat_pb2.Empty - method = client.noop_method - elif req.method == clientcompat_pb2.ClientCompatMessage.METHOD: - input_type = clientcompat_pb2.Req - method = client.method - - req = input_type.FromString(req.request) - return method(req) - - -if __name__ == "__main__": - main() diff --git a/clientcompat/pycompat/pycompat.sh b/clientcompat/pycompat/pycompat.sh deleted file mode 100644 index fec901c9..00000000 --- a/clientcompat/pycompat/pycompat.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You may not -# use this file except in compliance with the License. A copy of the License is -# located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the "license" file accompanying this file. This file is distributed on -# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -# express or implied. See the License for the specific language governing -# permissions and limitations under the License. - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -source "$DIR/venv/bin/activate" -exec pycompat.py "$@" diff --git a/clientcompat/pycompat/setup.py b/clientcompat/pycompat/setup.py deleted file mode 100644 index 46b9f0ee..00000000 --- a/clientcompat/pycompat/setup.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You may not -# use this file except in compliance with the License. A copy of the License is -# located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the "license" file accompanying this file. This file is distributed on -# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -# express or implied. See the License for the specific language governing -# permissions and limitations under the License. - -from distutils.core import setup - -setup( - name='pycompat', - description='Twirp-Python compatibility test client', - py_modules=['clientcompat_pb2', 'clientcompat_pb2_twirp'], - install_requires=['protobuf'], - scripts=['pycompat.py'], -) diff --git a/example/gen.go b/example/gen.go index c5c91b2f..a8f8a11f 100644 --- a/example/gen.go +++ b/example/gen.go @@ -13,4 +13,4 @@ package example -//go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. --python_out=. --twirp_python_out=. service.proto +//go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. service.proto diff --git a/example/service_pb2.py b/example/service_pb2.py deleted file mode 100644 index f032f4ba..00000000 --- a/example/service_pb2.py +++ /dev/null @@ -1,151 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: service.proto -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor.FileDescriptor( - name='service.proto', - package='twitch.twirp.example', - syntax='proto3', - serialized_options=b'Z\010/example', - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\rservice.proto\x12\x14twitch.twirp.example\"0\n\x03Hat\x12\x0c\n\x04size\x18\x01 \x01(\x05\x12\r\n\x05\x63olor\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\"\x16\n\x04Size\x12\x0e\n\x06inches\x18\x01 \x01(\x05\x32O\n\x0bHaberdasher\x12@\n\x07MakeHat\x12\x1a.twitch.twirp.example.Size\x1a\x19.twitch.twirp.example.HatB\nZ\x08/exampleb\x06proto3' -) - - - - -_HAT = _descriptor.Descriptor( - name='Hat', - full_name='twitch.twirp.example.Hat', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='size', full_name='twitch.twirp.example.Hat.size', index=0, - number=1, type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='color', full_name='twitch.twirp.example.Hat.color', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='name', full_name='twitch.twirp.example.Hat.name', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=39, - serialized_end=87, -) - - -_SIZE = _descriptor.Descriptor( - name='Size', - full_name='twitch.twirp.example.Size', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='inches', full_name='twitch.twirp.example.Size.inches', index=0, - number=1, type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=89, - serialized_end=111, -) - -DESCRIPTOR.message_types_by_name['Hat'] = _HAT -DESCRIPTOR.message_types_by_name['Size'] = _SIZE -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -Hat = _reflection.GeneratedProtocolMessageType('Hat', (_message.Message,), { - 'DESCRIPTOR' : _HAT, - '__module__' : 'service_pb2' - # @@protoc_insertion_point(class_scope:twitch.twirp.example.Hat) - }) -_sym_db.RegisterMessage(Hat) - -Size = _reflection.GeneratedProtocolMessageType('Size', (_message.Message,), { - 'DESCRIPTOR' : _SIZE, - '__module__' : 'service_pb2' - # @@protoc_insertion_point(class_scope:twitch.twirp.example.Size) - }) -_sym_db.RegisterMessage(Size) - - -DESCRIPTOR._options = None - -_HABERDASHER = _descriptor.ServiceDescriptor( - name='Haberdasher', - full_name='twitch.twirp.example.Haberdasher', - file=DESCRIPTOR, - index=0, - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_start=113, - serialized_end=192, - methods=[ - _descriptor.MethodDescriptor( - name='MakeHat', - full_name='twitch.twirp.example.Haberdasher.MakeHat', - index=0, - containing_service=None, - input_type=_SIZE, - output_type=_HAT, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), -]) -_sym_db.RegisterServiceDescriptor(_HABERDASHER) - -DESCRIPTOR.services_by_name['Haberdasher'] = _HABERDASHER - -# @@protoc_insertion_point(module_scope) diff --git a/example/service_pb2_twirp.py b/example/service_pb2_twirp.py deleted file mode 100644 index 0866e346..00000000 --- a/example/service_pb2_twirp.py +++ /dev/null @@ -1,84 +0,0 @@ -# Code generated by protoc-gen-twirp_python v8.0.0, DO NOT EDIT. -# source: service.proto - -try: - import httplib - from urllib2 import Request, HTTPError, urlopen -except ImportError: - import http.client as httplib - from urllib.request import Request, urlopen - from urllib.error import HTTPError -import json -from google.protobuf import symbol_database as _symbol_database -import sys - -_sym_db = _symbol_database.Default() - -class TwirpException(httplib.HTTPException): - def __init__(self, code, message, meta): - self.code = code - self.message = message - self.meta = meta - super(TwirpException, self).__init__(message) - - @classmethod - def from_http_err(cls, err): - try: - jsonerr = json.load(err) - code = jsonerr["code"] - msg = jsonerr["msg"] - meta = jsonerr.get("meta") - if meta is None: - meta = {} - except: - code = "internal" - msg = "Error from intermediary with HTTP status code {} {}".format( - err.code, httplib.responses[err.code], - ) - meta = {} - return cls(code, msg, meta) - -class HaberdasherClient(object): - """ - A Haberdasher makes hats for clients. - """ - - def __init__(self, server_address): - """Creates a new client for the Haberdasher service. - - Args: - server_address: The address of the server to send requests to, in - the full protocol://host:port form. - """ - if sys.version_info[0] > 2: - self.__target = server_address - else: - self.__target = server_address.encode('ascii') - self.__service_name = "twitch.twirp.example.Haberdasher" - - def __make_request(self, body, full_method): - req = Request( - url=self.__target + "/twirp" + full_method, - data=body, - headers={"Content-Type": "application/protobuf"}, - ) - try: - resp = urlopen(req) - except HTTPError as err: - raise TwirpException.from_http_err(err) - - return resp.read() - - def make_hat(self, size): - """ - MakeHat produces a hat of mysterious, randomly-selected color! - """ - - serialize = _sym_db.GetSymbol("twitch.twirp.example.Size").SerializeToString - deserialize = _sym_db.GetSymbol("twitch.twirp.example.Hat").FromString - - full_method = "/{}/{}".format(self.__service_name, "MakeHat") - body = serialize(size) - resp_str = self.__make_request(body=body, full_method=full_method) - return deserialize(resp_str) - diff --git a/internal/twirptest/google_protobuf_imports/service.twirp.go b/internal/twirptest/google_protobuf_imports/service.twirp.go index 4586fc2f..7ed2c21c 100644 --- a/internal/twirptest/google_protobuf_imports/service.twirp.go +++ b/internal/twirptest/google_protobuf_imports/service.twirp.go @@ -23,8 +23,8 @@ import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" -import google_protobuf1 "google.golang.org/protobuf/types/known/wrapperspb" import google_protobuf "google.golang.org/protobuf/types/known/emptypb" +import google_protobuf1 "google.golang.org/protobuf/types/known/wrapperspb" import bytes "bytes" import io "io" diff --git a/protoc-gen-twirp_python/main.go b/protoc-gen-twirp_python/main.go deleted file mode 100644 index 39b69939..00000000 --- a/protoc-gen-twirp_python/main.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"). You may not -// use this file except in compliance with the License. A copy of the License is -// located at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// or in the "license" file accompanying this file. This file is distributed on -// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -// express or implied. See the License for the specific language governing -// permissions and limitations under the License. - -package main - -import ( - "bytes" - "flag" - "fmt" - "os" - "path" - "strconv" - "strings" - - "google.golang.org/protobuf/proto" - descriptor "google.golang.org/protobuf/types/descriptorpb" - plugin "google.golang.org/protobuf/types/pluginpb" - - "github.com/twitchtv/twirp/internal/gen" - "github.com/twitchtv/twirp/internal/gen/stringutils" - "github.com/twitchtv/twirp/internal/gen/typemap" -) - -func main() { - versionFlag := flag.Bool("version", false, "print version and exit") - flag.Parse() - if *versionFlag { - fmt.Println(gen.Version) - os.Exit(0) - } - - g := newGenerator() - gen.Main(g) -} - -func newGenerator() *generator { - return &generator{output: new(bytes.Buffer)} -} - -type generator struct { - reg *typemap.Registry - output *bytes.Buffer -} - -func (g *generator) Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse { - genFiles := gen.FilesToGenerate(in) - g.reg = typemap.New(in.ProtoFile) - - resp := new(plugin.CodeGeneratorResponse) - for _, f := range genFiles { - respFile := g.generateFile(f) - if respFile != nil { - resp.File = append(resp.File, respFile) - } - } - - return resp -} - -func (g *generator) generateFile(file *descriptor.FileDescriptorProto) *plugin.CodeGeneratorResponse_File { - g.P("# Code generated by protoc-gen-twirp_python ", gen.Version, ", DO NOT EDIT.") - g.P("# source: ", file.GetName()) - g.P() - g.P(`try:`) - g.P(` import httplib`) - g.P(` from urllib2 import Request, HTTPError, urlopen`) - g.P(`except ImportError:`) - g.P(` import http.client as httplib`) - g.P(` from urllib.request import Request, urlopen`) - g.P(` from urllib.error import HTTPError`) - g.P(`import json`) - g.P(`from google.protobuf import symbol_database as _symbol_database`) - g.P(`import sys`) - g.P() - g.P(`_sym_db = _symbol_database.Default()`) - g.P() - g.P(`class TwirpException(httplib.HTTPException):`) - g.P(` def __init__(self, code, message, meta):`) - g.P(` self.code = code`) - g.P(` self.message = message`) - g.P(` self.meta = meta`) - g.P(` super(TwirpException, self).__init__(message)`) - g.P() - g.P(` @classmethod`) - g.P(` def from_http_err(cls, err):`) - g.P(` try:`) - g.P(` jsonerr = json.load(err)`) - g.P(` code = jsonerr["code"]`) - g.P(` msg = jsonerr["msg"]`) - g.P(` meta = jsonerr.get("meta")`) - g.P(` if meta is None:`) - g.P(` meta = {}`) - g.P(` except:`) - g.P(` code = "internal"`) - g.P(` msg = "Error from intermediary with HTTP status code {} {}".format(`) - g.P(` err.code, httplib.responses[err.code],`) - g.P(` )`) - g.P(` meta = {}`) - g.P(` return cls(code, msg, meta)`) - g.P() - for _, service := range file.Service { - g.generateProtobufClient(file, service) - } - - resp := new(plugin.CodeGeneratorResponse_File) - resp.Name = proto.String(pyFileName(file)) - resp.Content = proto.String(g.output.String()) - g.output.Reset() - - return resp -} - -func (g *generator) generateProtobufClient(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) { - g.P(`class `, clientName(service), `(object):`) - comments, err := g.reg.ServiceComments(file, service) - if err == nil && comments.Leading != "" { - g.P(` """`) - g.printComments(comments, ` `) - g.P(` """`) - g.P() - } - g.P(` def __init__(self, server_address):`) - g.P(` """Creates a new client for the `, serviceName(service), ` service.`) - g.P() - g.P(` Args:`) - g.P(` server_address: The address of the server to send requests to, in`) - g.P(` the full protocol://host:port form.`) - g.P(` """`) - g.P(` if sys.version_info[0] > 2:`) - g.P(` self.__target = server_address`) - g.P(` else:`) - g.P(` self.__target = server_address.encode('ascii')`) - g.P(` self.__service_name = `, strconv.Quote(fullServiceName(file, service))) - g.P() - g.P(` def __make_request(self, body, full_method):`) - g.P(` req = Request(`) - g.P(` url=self.__target + "/twirp" + full_method,`) - g.P(` data=body,`) - g.P(` headers={"Content-Type": "application/protobuf"},`) - g.P(` )`) - g.P(` try:`) - g.P(` resp = urlopen(req)`) - g.P(` except HTTPError as err:`) - g.P(` raise TwirpException.from_http_err(err)`) - g.P(``) - g.P(` return resp.read()`) - g.P() - - for _, method := range service.Method { - methName := methodName(method) - inputName := methodInputName(method) - - // Be careful not to write code that overwrites the input parameter. - for _, x := range []string{"self", "_sym_db", "full_method", "body", - "serialize", "deserialize", "resp_str"} { - if inputName == x { - inputName = inputName + "_" - } - } - - g.P(` def `, methName, `(self, `, inputName, `):`) - comments, err := g.reg.MethodComments(file, service, method) - if err == nil && comments.Leading != "" { - g.P(` """`) - g.printComments(comments, ` `) - g.P(` """`) - g.P() - } - g.P(` serialize = _sym_db.GetSymbol(`, - strconv.Quote(strings.TrimPrefix(method.GetInputType(), ".")), `).SerializeToString`) - g.P(` deserialize = _sym_db.GetSymbol(`, - strconv.Quote(strings.TrimPrefix(method.GetOutputType(), ".")), `).FromString`) - g.P() - g.P(` full_method = "/{}/{}".format(self.__service_name, `, strconv.Quote(method.GetName()), `)`) - g.P(` body = serialize(`, inputName, `)`) - g.P(` resp_str = self.__make_request(body=body, full_method=full_method)`) - g.P(` return deserialize(resp_str)`) - g.P() - } -} - -func (g *generator) P(args ...string) { - for _, v := range args { - g.output.WriteString(v) - } - g.output.WriteByte('\n') -} - -func (g *generator) printComments(comments typemap.DefinitionComments, prefix string) { - text := strings.TrimSuffix(comments.Leading, "\n") - for _, line := range strings.Split(text, "\n") { - g.P(prefix, strings.TrimPrefix(line, " ")) - } -} - -func serviceName(service *descriptor.ServiceDescriptorProto) string { - return stringutils.CamelCase(service.GetName()) -} - -func clientName(service *descriptor.ServiceDescriptorProto) string { - return serviceName(service) + "Client" -} - -func fullServiceName(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) string { - name := serviceName(service) - if pkg := file.GetPackage(); pkg != "" { - name = pkg + "." + name - } - return name -} - -func methodName(method *descriptor.MethodDescriptorProto) string { - return stringutils.SnakeCase(method.GetName()) -} - -// methodInputName returns the basename of the input type of a method in snake -// case. -func methodInputName(meth *descriptor.MethodDescriptorProto) string { - fullName := meth.GetInputType() - split := strings.Split(fullName, ".") - return stringutils.SnakeCase(split[len(split)-1]) -} - -func pyFileName(f *descriptor.FileDescriptorProto) string { - name := *f.Name - if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" { - name = name[:len(name)-len(ext)] - } - name += "_pb2_twirp.py" - return name -} diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index a4d3ee34..00000000 --- a/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -certifi==2017.4.17 -chardet==3.0.4 -idna==2.5 -protobuf==3.5.1 -requests==2.21.0 -six==1.10.0 -urllib3>=1.24.2