Repository: avro Updated Branches: refs/heads/master 37ce7f724 -> 0550d2cce
AVRO-2001: Adding support for doc attribute Signed-off-by: sacharya <[email protected]> Signed-off-by: Tim Perkins <[email protected]> Signed-off-by: Sean Busbey <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/avro/repo Commit: http://git-wip-us.apache.org/repos/asf/avro/commit/0550d2cc Tree: http://git-wip-us.apache.org/repos/asf/avro/tree/0550d2cc Diff: http://git-wip-us.apache.org/repos/asf/avro/diff/0550d2cc Branch: refs/heads/master Commit: 0550d2cce2793d1b810960a652f03fadf88b02ff Parents: 37ce7f7 Author: lostphilosopher <[email protected]> Authored: Wed Feb 15 13:05:43 2017 -0600 Committer: sacharya <[email protected]> Committed: Mon Apr 3 18:11:24 2017 -0500 ---------------------------------------------------------------------- lang/ruby/lib/avro/protocol.rb | 17 ++++--- lang/ruby/lib/avro/schema.rb | 32 +++++++----- lang/ruby/test/test_protocol.rb | 39 ++++++++++++-- lang/ruby/test/test_schema.rb | 98 ++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/avro/blob/0550d2cc/lang/ruby/lib/avro/protocol.rb ---------------------------------------------------------------------- diff --git a/lang/ruby/lib/avro/protocol.rb b/lang/ruby/lib/avro/protocol.rb index 6c210e1..989f270 100644 --- a/lang/ruby/lib/avro/protocol.rb +++ b/lang/ruby/lib/avro/protocol.rb @@ -20,7 +20,7 @@ module Avro VALID_TYPE_SCHEMA_TYPES_SYM = Set.new(VALID_TYPE_SCHEMA_TYPES.map(&:to_sym)) class ProtocolParseError < Avro::AvroError; end - attr_reader :name, :namespace, :types, :messages, :md5 + attr_reader :name, :namespace, :types, :messages, :md5, :doc def self.parse(protocol_string) json_data = MultiJson.load(protocol_string) @@ -29,13 +29,14 @@ module Avro namespace = json_data['namespace'] types = json_data['types'] messages = json_data['messages'] - Protocol.new(name, namespace, types, messages) + doc = json_data['doc'] + Protocol.new(name, namespace, types, messages, doc) else raise ProtocolParseError, "Not a JSON object: #{json_data}" end end - def initialize(name, namespace=nil, types=nil, messages=nil) + def initialize(name, namespace=nil, types=nil, messages=nil, doc=nil) # Ensure valid ctor args if !name raise ProtocolParseError, 'Protocols must have a non-empty name.' @@ -55,6 +56,7 @@ module Avro @types = parse_types(types, type_names) @messages = parse_messages(messages, type_names) @md5 = Digest::MD5.digest(to_s) + @doc = doc end def to_s @@ -92,7 +94,8 @@ module Avro request = body['request'] response = body['response'] errors = body['errors'] - message_objects[name] = Message.new(name, request, response, errors, names, namespace) + doc = body['doc'] + message_objects[name] = Message.new(name, request, response, errors, names, namespace, doc) end message_objects end @@ -111,14 +114,15 @@ module Avro end class Message - attr_reader :name, :request, :response, :errors, :default_namespace + attr_reader :name, :request, :response, :errors, :default_namespace, :doc - def initialize(name, request, response, errors=nil, names=nil, default_namespace=nil) + def initialize(name, request, response, errors=nil, names=nil, default_namespace=nil, doc=nil) @name = name @default_namespace = default_namespace @request = parse_request(request, names) @response = parse_response(response, names) @errors = parse_errors(errors, names) if errors + @doc = doc end def to_avro(names=Set.new) @@ -127,6 +131,7 @@ module Avro 'response' => response.to_avro(names) }.tap do |hash| hash['errors'] = errors.to_avro(names) if errors + hash['doc'] = @doc if @doc end end http://git-wip-us.apache.org/repos/asf/avro/blob/0550d2cc/lang/ruby/lib/avro/schema.rb ---------------------------------------------------------------------- diff --git a/lang/ruby/lib/avro/schema.rb b/lang/ruby/lib/avro/schema.rb index 477528e..5038311 100644 --- a/lang/ruby/lib/avro/schema.rb +++ b/lang/ruby/lib/avro/schema.rb @@ -61,10 +61,12 @@ module Avro return FixedSchema.new(name, namespace, size, names) when :enum symbols = json_obj['symbols'] - return EnumSchema.new(name, namespace, symbols, names) + doc = json_obj['doc'] + return EnumSchema.new(name, namespace, symbols, names, doc) when :record, :error fields = json_obj['fields'] - return RecordSchema.new(name, namespace, fields, names, type_sym) + doc = json_obj['doc'] + return RecordSchema.new(name, namespace, fields, names, type_sym, doc) else raise SchemaParseError.new("Unknown named type: #{type}") end @@ -152,9 +154,10 @@ module Avro class NamedSchema < Schema attr_reader :name, :namespace - def initialize(type, name, namespace=nil, names=nil) + def initialize(type, name, namespace=nil, names=nil, doc=nil) super(type) @name, @namespace = Name.extract_namespace(name, namespace) + @doc = doc names = Name.add_name(names, self) end @@ -165,6 +168,7 @@ module Avro end props = {'name' => @name} props.merge!('namespace' => @namespace) if @namespace + props.merge!('doc' => @doc) if @doc super.merge props end @@ -174,7 +178,7 @@ module Avro end class RecordSchema < NamedSchema - attr_reader :fields + attr_reader :fields, :doc def self.make_field_objects(field_data, names, namespace=nil) field_objects, field_names = [], Set.new @@ -184,7 +188,8 @@ module Avro name = field['name'] default = field.key?('default') ? field['default'] : :no_default order = field['order'] - new_field = Field.new(type, name, default, order, names, namespace) + doc = field['doc'] + new_field = Field.new(type, name, default, order, names, namespace, doc) # make sure field name has not been used yet if field_names.include?(new_field.name) raise SchemaParseError, "Field name #{new_field.name.inspect} is already in use" @@ -198,12 +203,12 @@ module Avro field_objects end - def initialize(name, namespace, fields, names=nil, schema_type=:record) + def initialize(name, namespace, fields, names=nil, schema_type=:record, doc=nil) if schema_type == :request || schema_type == 'request' @type_sym = schema_type.to_sym @namespace = namespace else - super(schema_type, name, namespace, names) + super(schema_type, name, namespace, names, doc) end @fields = RecordSchema.make_field_objects(fields, names, self.namespace) end @@ -280,13 +285,14 @@ module Avro end class EnumSchema < NamedSchema - attr_reader :symbols - def initialize(name, space, symbols, names=nil) + attr_reader :symbols, :doc + + def initialize(name, space, symbols, names=nil, doc=nil) if symbols.uniq.length < symbols.length fail_msg = 'Duplicate symbol: %s' % symbols raise Avro::SchemaParseError, fail_msg end - super(:enum, name, space, names) + super(:enum, name, space, names, doc) @symbols = symbols end @@ -332,19 +338,21 @@ module Avro end class Field < Schema - attr_reader :type, :name, :default, :order + attr_reader :type, :name, :default, :order, :doc - def initialize(type, name, default=:no_default, order=nil, names=nil, namespace=nil) + def initialize(type, name, default=:no_default, order=nil, names=nil, namespace=nil, doc=nil) @type = subparse(type, names, namespace) @name = name @default = default @order = order + @doc = doc end def to_avro(names=Set.new) {'name' => name, 'type' => type.to_avro(names)}.tap do |avro| avro['default'] = default unless default == :no_default avro['order'] = order if order + avro['doc'] = doc if doc end end end http://git-wip-us.apache.org/repos/asf/avro/blob/0550d2cc/lang/ruby/test/test_protocol.rb ---------------------------------------------------------------------- diff --git a/lang/ruby/test/test_protocol.rb b/lang/ruby/test/test_protocol.rb index fda3882..1b036fe 100644 --- a/lang/ruby/test/test_protocol.rb +++ b/lang/ruby/test/test_protocol.rb @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -139,7 +139,7 @@ EOS } EOS - ExampleProtocol.new(<<-EOS, true) + ExampleProtocol.new(<<-EOS, true), {"namespace": "org.apache.avro.test", "protocol": "BulkData", @@ -161,6 +161,29 @@ EOS } EOS + ExampleProtocol.new(<<-EOS, true), +{ + "namespace": "com.acme", + "protocol": "HelloWorld", + "doc": "protocol_documentation", + + "types": [ + {"name": "Greeting", "type": "record", "fields": [ + {"name": "message", "type": "string"}]}, + {"name": "Curse", "type": "error", "fields": [ + {"name": "message", "type": "string"}]} + ], + + "messages": { + "hello": { + "doc": "message_documentation", + "request": [{"name": "greeting", "type": "Greeting" }], + "response": "Greeting", + "errors": ["Curse"] + } + } +} +EOS ] Protocol = Avro::Protocol @@ -196,4 +219,14 @@ EOS assert_equal type.namespace, 'com.acme' end end + + def test_protocol_doc_attribute + original = Protocol.parse(EXAMPLES.last.protocol_string) + assert_equal 'protocol_documentation', original.doc + end + + def test_protocol_message_doc_attribute + original = Protocol.parse(EXAMPLES.last.protocol_string) + assert_equal 'message_documentation', original.messages['hello'].doc + end end http://git-wip-us.apache.org/repos/asf/avro/blob/0550d2cc/lang/ruby/test/test_schema.rb ---------------------------------------------------------------------- diff --git a/lang/ruby/test/test_schema.rb b/lang/ruby/test/test_schema.rb index a011823..417d511 100644 --- a/lang/ruby/test/test_schema.rb +++ b/lang/ruby/test/test_schema.rb @@ -160,4 +160,102 @@ class TestSchema < Test::Unit::TestCase ] } end + + def test_record_field_doc_attribute + field_schema_json = Avro::Schema.parse <<-SCHEMA + { + "type": "record", + "name": "Record", + "namespace": "my.name.space", + "fields": [ + { + "name": "name", + "type": "boolean", + "doc": "documentation" + } + ] + } + SCHEMA + + field_schema_hash = + { + 'type' => 'record', + 'name' => 'Record', + 'namespace' => 'my.name.space', + 'fields' => [ + { + 'name' => 'name', + 'type' => 'boolean', + 'doc' => 'documentation' + } + ] + } + + assert_equal field_schema_hash, field_schema_json.to_avro + end + + def test_record_doc_attribute + record_schema_json = Avro::Schema.parse <<-SCHEMA + { + "type": "record", + "name": "Record", + "namespace": "my.name.space", + "doc": "documentation", + "fields": [ + { + "name": "name", + "type": "boolean" + } + ] + } + SCHEMA + + record_schema_hash = + { + 'type' => 'record', + 'name' => 'Record', + 'namespace' => 'my.name.space', + 'doc' => 'documentation', + 'fields' => [ + { + 'name' => 'name', + 'type' => 'boolean' + } + ] + } + + assert_equal record_schema_hash, record_schema_json.to_avro + end + + def test_enum_doc_attribute + enum_schema_json = Avro::Schema.parse <<-SCHEMA + { + "type": "enum", + "name": "Enum", + "namespace": "my.name.space", + "doc": "documentation", + "symbols" : [ + "SPADES", + "HEARTS", + "DIAMONDS", + "CLUBS" + ] + } + SCHEMA + + enum_schema_hash = + { + 'type' => 'enum', + 'name' => 'Enum', + 'namespace' => 'my.name.space', + 'doc' => 'documentation', + 'symbols' => [ + 'SPADES', + 'HEARTS', + 'DIAMONDS', + 'CLUBS' + ] + } + assert_equal enum_schema_hash, enum_schema_json.to_avro + end end
