diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e8741a8b..ab70543fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,12 @@ jobs: with: gem-name: 'smithy-json' + smithy-xml: + needs: [smithy-schema] + uses: ./.github/workflows/test.yml + with: + gem-name: 'smithy-xml' + smithy-client: needs: [smithy-schema] uses: ./.github/workflows/test.yml diff --git a/Gemfile b/Gemfile index 80f854113..722ddde53 100644 --- a/Gemfile +++ b/Gemfile @@ -11,6 +11,7 @@ gem 'smithy-client', path: 'gems/smithy-client' gem 'smithy-json', path: 'gems/smithy-json' # gem 'smithy-server', path: 'gems/smithy-server' gem 'smithy-schema', path: 'gems/smithy-schema' +gem 'smithy-xml', path: 'gems/smithy-xml' group :development do gem 'byebug', platforms: :ruby diff --git a/gems/smithy-cbor/lib/smithy-cbor/builder.rb b/gems/smithy-cbor/lib/smithy-cbor/builder.rb index 703f42097..076e718dd 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/builder.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/builder.rb @@ -61,7 +61,7 @@ def structure(ref, values) value = values[member_name] next if value.nil? - data[member_ref.member_name] = shape(member_ref, value) + data[member_ref.location_name] = shape(member_ref, value) end end @@ -71,12 +71,12 @@ def union(ref, values) # rubocop:disable Metrics/AbcSize data = {} if values.is_a?(Schema::Union) _name, member_ref = ref.shape.member_by_type(values.class) - data[member_ref.member_name] = shape(member_ref, values.value) + data[member_ref.location_name] = shape(member_ref, values.value) else key, value = values.first if ref.shape.member?(key) member_ref = ref.shape.member(key) - data[member_ref.member_name] = shape(member_ref, value) + data[member_ref.location_name] = shape(member_ref, value) end end data diff --git a/gems/smithy-cbor/lib/smithy-cbor/parser.rb b/gems/smithy-cbor/lib/smithy-cbor/parser.rb index 96f638aaa..18b1fcb96 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/parser.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/parser.rb @@ -56,7 +56,7 @@ def map(ref, values, target = nil) def structure(ref, values, target = nil) target = ref.shape.type.new if target.nil? ref.shape.members.each do |member_name, member_ref| - value = values[member_ref.member_name] + value = values[member_ref.location_name] target[member_name] = shape(member_ref, value) unless value.nil? end target @@ -64,7 +64,7 @@ def structure(ref, values, target = nil) def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize ref.shape.members.each do |member_name, member_ref| - value = values[member_ref.member_name] + value = values[member_ref.location_name] next if value.nil? target = ref.shape.member_type(member_name) if target.nil? diff --git a/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb b/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb index 73aeba5a9..0e174bd3e 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb @@ -53,7 +53,7 @@ def label_value(input, label, params) name = nil input.shape.members.each do |member_name, member_ref| next unless member_ref.traits.key?('smithy.api#hostLabel') - next unless member_ref.member_name == label + next unless member_ref.location_name == label name = member_name end diff --git a/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb b/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb index 6486017ab..ef18755f5 100644 --- a/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb +++ b/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb @@ -56,7 +56,7 @@ def union(ref, visited) def scalar(ref) case ref.shape when BigDecimalShape then BigDecimal(0) - when BlobShape, EnumShape, StringShape then ref.member_name + when BlobShape, EnumShape, StringShape then ref.location_name when BooleanShape then false when IntegerShape, IntEnumShape then 0 when FloatShape then 0.0 diff --git a/gems/smithy-json/lib/smithy-json/builder.rb b/gems/smithy-json/lib/smithy-json/builder.rb index 6230b2ab4..c55cf456d 100644 --- a/gems/smithy-json/lib/smithy-json/builder.rb +++ b/gems/smithy-json/lib/smithy-json/builder.rb @@ -104,9 +104,9 @@ def union(ref, values) # rubocop:disable Metrics/AbcSize end def location_name(ref) - return ref.member_name unless @json_name + return ref.location_name unless @json_name - ref.traits['smithy.api#jsonName'] || ref.member_name + ref.traits['smithy.api#jsonName'] || ref.location_name end end end diff --git a/gems/smithy-json/lib/smithy-json/codec.rb b/gems/smithy-json/lib/smithy-json/codec.rb index 700f105be..82e8abd25 100644 --- a/gems/smithy-json/lib/smithy-json/codec.rb +++ b/gems/smithy-json/lib/smithy-json/codec.rb @@ -2,7 +2,7 @@ module Smithy module Json - # @api private + # Codec that builds and parses in JSON format. class Codec # @param [Hash] options def initialize(options = {}) diff --git a/gems/smithy-json/lib/smithy-json/parser.rb b/gems/smithy-json/lib/smithy-json/parser.rb index b615f3f25..e21c05c6a 100644 --- a/gems/smithy-json/lib/smithy-json/parser.rb +++ b/gems/smithy-json/lib/smithy-json/parser.rb @@ -104,9 +104,9 @@ def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize end def location_name(ref) - return ref.member_name unless @json_name + return ref.location_name unless @json_name - ref.traits['smithy.api#jsonName'] || ref.member_name + ref.traits['smithy.api#jsonName'] || ref.location_name end def sparse?(shape) diff --git a/gems/smithy-json/spec/smithy-json/parser_spec.rb b/gems/smithy-json/spec/smithy-json/parser_spec.rb index 411f1361a..13fb46127 100644 --- a/gems/smithy-json/spec/smithy-json/parser_spec.rb +++ b/gems/smithy-json/spec/smithy-json/parser_spec.rb @@ -74,7 +74,7 @@ module Json expect(subject.parse(structure_shape, bytes).to_h).to eq(expected) end - it 'builds and parses structures with jsonName' do + it 'parses structures with jsonName' do subject = described_class.new(json_name: true) shapes['smithy.ruby.tests#Structure']['members']['string'] = { 'target' => 'smithy.api#String', diff --git a/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb b/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb index 13d7b09b2..7104a1f34 100644 --- a/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb +++ b/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb @@ -115,9 +115,9 @@ def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize end def location_name(ref) - return ref.member_name unless @json_name + return ref.location_name unless @json_name - ref.traits['smithy.api#jsonName'] || ref.member_name + ref.traits['smithy.api#jsonName'] || ref.location_name end end end diff --git a/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb b/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb index f6a1ef676..3f98dfe21 100644 --- a/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb +++ b/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb @@ -147,9 +147,9 @@ def union(ref, values) end def location_name(ref) - return ref.member_name unless @json_name + return ref.location_name unless @json_name - ref.traits['smithy.api#jsonName'] || ref.member_name + ref.traits['smithy.api#jsonName'] || ref.location_name end def normalize_timestamp_value(value) @@ -164,7 +164,7 @@ def resolve_member_ref(ref, name) return ref.shape.member(name) if ref.shape.member?(name) ref.shape.members.values.find do |member_ref| - member_ref.traits['smithy.api#jsonName'] == name || member_ref.member_name == name + member_ref.traits['smithy.api#jsonName'] == name || member_ref.location_name == name end end @@ -173,7 +173,7 @@ def resolve_value(member_name, member_ref, values) value = values[json_name] return value unless value.nil? end - values[member_name] || values[member_ref.member_name] + values[member_name] || values[member_ref.location_name] end end end diff --git a/gems/smithy-schema/lib/smithy-schema/shapes.rb b/gems/smithy-schema/lib/smithy-schema/shapes.rb index b23bada97..caa8e94ba 100644 --- a/gems/smithy-schema/lib/smithy-schema/shapes.rb +++ b/gems/smithy-schema/lib/smithy-schema/shapes.rb @@ -38,7 +38,7 @@ def []=(key, value) class ShapeRef def initialize(options = {}) @shape = options[:shape] - @member_name = options[:member_name] + @location_name = options[:location_name] @traits = options[:traits] || {} @metadata = {} end @@ -47,7 +47,7 @@ def initialize(options = {}) attr_accessor :shape # @return [String, nil] - attr_accessor :member_name + attr_accessor :location_name # @return [Hash] attr_accessor :traits @@ -326,49 +326,57 @@ def member_by_type(type) # Prelude shape definitions. module Prelude - BigDecimal = BigDecimalShape.new(id: 'smithy.api#BigDecimal') - BigInteger = IntegerShape.new(id: 'smithy.api#BigInteger') - Blob = BlobShape.new(id: 'smithy.api#Blob') - Boolean = BooleanShape.new(id: 'smithy.api#Boolean') - Byte = IntegerShape.new(id: 'smithy.api#Byte') - Document = DocumentShape.new(id: 'smithy.api#Document') - Double = FloatShape.new(id: 'smithy.api#Double') - Float = FloatShape.new(id: 'smithy.api#Float') - Integer = IntegerShape.new(id: 'smithy.api#Integer') - Long = IntegerShape.new(id: 'smithy.api#Long') + BigDecimal = BigDecimalShape.new(id: 'smithy.api#BigDecimal', name: 'BigDecimal') + BigInteger = IntegerShape.new(id: 'smithy.api#BigInteger', name: 'BigInteger') + Blob = BlobShape.new(id: 'smithy.api#Blob', name: 'Blob') + Boolean = BooleanShape.new(id: 'smithy.api#Boolean', name: 'Boolean') + Byte = IntegerShape.new(id: 'smithy.api#Byte', name: 'Byte') + Document = DocumentShape.new(id: 'smithy.api#Document', name: 'Document') + Double = FloatShape.new(id: 'smithy.api#Double', name: 'Double') + Float = FloatShape.new(id: 'smithy.api#Float', name: 'Float') + Integer = IntegerShape.new(id: 'smithy.api#Integer', name: 'Integer') + Long = IntegerShape.new(id: 'smithy.api#Long', name: 'Long') PrimitiveBoolean = BooleanShape.new( id: 'smithy.api#PrimitiveBoolean', + name: 'PrimitiveBoolean', traits: { 'smithy.api#default' => false } ) PrimitiveByte = IntegerShape.new( id: 'smithy.api#PrimitiveByte', + name: 'PrimitiveByte', traits: { 'smithy.api#default' => 0 } ) PrimitiveDouble = FloatShape.new( id: 'smithy.api#PrimitiveDouble', + name: 'PrimitiveDouble', traits: { 'smithy.api#default' => 0 } ) PrimitiveFloat = FloatShape.new( id: 'smithy.api#PrimitiveFloat', + name: 'PrimitiveFloat', traits: { 'smithy.api#default' => 0 } ) PrimitiveInteger = IntegerShape.new( id: 'smithy.api#PrimitiveInteger', + name: 'PrimitiveInteger', traits: { 'smithy.api#default' => 0 } ) PrimitiveShort = IntegerShape.new( id: 'smithy.api#PrimitiveShort', + name: 'PrimitiveShort', traits: { 'smithy.api#default' => 0 } ) PrimitiveLong = IntegerShape.new( id: 'smithy.api#PrimitiveLong', + name: 'PrimitiveLong', traits: { 'smithy.api#default' => 0 } ) - Short = IntegerShape.new(id: 'smithy.api#Short') - String = StringShape.new(id: 'smithy.api#String') - Timestamp = TimestampShape.new(id: 'smithy.api#Timestamp') + Short = IntegerShape.new(id: 'smithy.api#Short', name: 'Short') + String = StringShape.new(id: 'smithy.api#String', name: 'String') + Timestamp = TimestampShape.new(id: 'smithy.api#Timestamp', name: 'Timestamp') Unit = StructureShape.new( id: 'smithy.api#Unit', + name: 'Unit', traits: { 'smithy.api#unitType' => {} } ) Unit.type = EmptyStructure diff --git a/gems/smithy-schema/lib/smithy-schema/structure.rb b/gems/smithy-schema/lib/smithy-schema/structure.rb index 9b7b615c8..3990736c4 100644 --- a/gems/smithy-schema/lib/smithy-schema/structure.rb +++ b/gems/smithy-schema/lib/smithy-schema/structure.rb @@ -26,6 +26,12 @@ def empty? values.compact == [] end + # @param [Symbol] member_name + # @return [Boolean] + def key?(member_name) + !self[member_name].nil? + end + private def _to_h_structure(obj) diff --git a/gems/smithy-schema/sig/smithy-schema/shapes.rbs b/gems/smithy-schema/sig/smithy-schema/shapes.rbs index 164c422b0..b21661af6 100644 --- a/gems/smithy-schema/sig/smithy-schema/shapes.rbs +++ b/gems/smithy-schema/sig/smithy-schema/shapes.rbs @@ -15,7 +15,7 @@ module Smithy def initialize: (?Hash[Symbol, untyped]) -> void attr_accessor shape: Shape - attr_accessor member_name: String? + attr_accessor location_name: String? attr_accessor traits: Hash[String, untyped] def []: (Symbol) -> Object def []=: (Symbol, Object) -> void diff --git a/gems/smithy-schema/sig/smithy-schema/structure.rbs b/gems/smithy-schema/sig/smithy-schema/structure.rbs index a1dd25919..f44e3b749 100644 --- a/gems/smithy-schema/sig/smithy-schema/structure.rbs +++ b/gems/smithy-schema/sig/smithy-schema/structure.rbs @@ -3,6 +3,7 @@ module Smithy module Structure def to_h: () -> ::Hash[Symbol, ::Object] def empty?: () -> bool + def key?: (Symbol) -> bool end end end \ No newline at end of file diff --git a/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb b/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb index 69ea42ca3..9ac332fa2 100644 --- a/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb +++ b/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb @@ -54,12 +54,12 @@ module Shapes end it 'defaults a location name to nil' do - expect(subject.member_name).to be_nil + expect(subject.location_name).to be_nil end - it 'stores the member name as a location name' do - subject = ShapeRef.new(member_name: 'foo') - expect(subject.member_name).to eq('foo') + it 'stores a location name' do + subject = ShapeRef.new(location_name: 'foo') + expect(subject.location_name).to eq('foo') end it 'defaults traits to empty hash' do diff --git a/gems/smithy-schema/spec/smithy-schema/structure_spec.rb b/gems/smithy-schema/spec/smithy-schema/structure_spec.rb index 1d37edad5..7e84220d1 100644 --- a/gems/smithy-schema/spec/smithy-schema/structure_spec.rb +++ b/gems/smithy-schema/spec/smithy-schema/structure_spec.rb @@ -71,6 +71,17 @@ module Schema expect(structure.new(value: 'not nil').empty?).to be false end end + + describe '#key?' do + it 'returns false if the value is nil' do + empty_struct = structure.new + expect(empty_struct.key?(:value)).to be false + end + + it 'returns true if the value is not nil' do + expect(subject.key?(:value)).to be true + end + end end end end diff --git a/gems/smithy-xml/lib/smithy-xml/builder.rb b/gems/smithy-xml/lib/smithy-xml/builder.rb index f55882af2..3ef193a17 100644 --- a/gems/smithy-xml/lib/smithy-xml/builder.rb +++ b/gems/smithy-xml/lib/smithy-xml/builder.rb @@ -17,7 +17,7 @@ def build(shape, data, target = nil) ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape) target ||= [] @builder = DocBuilder.new(target: target, indent: @indent, pad: @pad) - structure(location_name(ref, ref.member_name), ref, data) + structure(ref.location_name || ref.shape.traits['smithy.api#xmlName'] || ref.shape.name, ref, data) target.join end @@ -30,6 +30,7 @@ def shape(name, ref, value) when MapShape then map(name, ref, value) when StructureShape then structure(name, ref, value) when TimestampShape then node(name, ref, timestamp(ref, value)) + when UnionShape then union(name, ref, value) else node(name, ref, value.to_s) end end @@ -66,7 +67,7 @@ def map(name, ref, values) # rubocop:disable Metrics/AbcSize else node(name, ref) do values.each do |key, value| - node('entry', ShapeRef.new) do + node('entry', ShapeRef.new(shape: MapShape.new)) do shape(location_name(key_ref, 'key'), key_ref, key) shape(location_name(value_ref, 'value'), value_ref, value) end @@ -76,12 +77,14 @@ def map(name, ref, values) # rubocop:disable Metrics/AbcSize end def structure(name, ref, values) + return node(name, ref) if values.empty? + node(name, ref, structure_attrs(ref, values)) do ref.shape.members.each do |member_name, member_ref| next if values[member_name].nil? next if xml_attribute?(member_ref) - shape(location_name(member_ref, member_ref.member_name), member_ref, values[member_name]) + shape(location_name(member_ref, member_ref.location_name), member_ref, values[member_name]) end end end @@ -89,7 +92,7 @@ def structure(name, ref, values) def structure_attrs(ref, values) ref.shape.members.each_with_object({}) do |(member_name, member_ref), attrs| if xml_attribute?(member_ref) && values.key?(member_name) - attrs[location_name(member_ref, member_ref.member_name)] = values[member_name] + attrs[location_name(member_ref, member_ref.location_name)] = values[member_name] end end end @@ -97,7 +100,7 @@ def structure_attrs(ref, values) def timestamp(ref, value) trait = 'smithy.api#timestampFormat' case ref.traits[trait] || ref.shape.traits[trait] - when 'epoch-seconds' then value.to_s + when 'epoch-seconds' then value.to_i.to_s when 'http-date' then value.utc.httpdate else # default to date-time @@ -105,6 +108,23 @@ def timestamp(ref, value) end end + def union(name, ref, values) # rubocop:disable Metrics/AbcSize + return node(name, ref) if values.empty? + + node(name, ref, structure_attrs(ref, values)) do + if values.is_a?(Schema::Union) + _name, member_ref = ref.shape.member_by_type(values.class) + shape(location_name(member_ref, member_ref.location_name), member_ref, values.value) + else + key, value = values.first + if ref.shape.member?(key) + member_ref = ref.shape.member(key) + shape(location_name(member_ref, member_ref.location_name), member_ref, value) + end + end + end + end + def location_name(ref, default = nil) ref.traits['smithy.api#xmlName'] || default end @@ -135,7 +155,9 @@ def node(name, ref, *args, &) end def shape_attrs(ref) - return {} unless (xmlns = ref.traits['smithy.api#xmlNamespace']) + trait = 'smithy.api#xmlNamespace' + xmlns = ref.traits[trait] || ref.shape.traits[trait] + return {} unless xmlns if (prefix = xmlns['prefix']) { "xmlns:#{prefix}" => xmlns['uri'] } diff --git a/gems/smithy-xml/lib/smithy-xml/doc_builder.rb b/gems/smithy-xml/lib/smithy-xml/doc_builder.rb index 2e1131fed..0431dad29 100644 --- a/gems/smithy-xml/lib/smithy-xml/doc_builder.rb +++ b/gems/smithy-xml/lib/smithy-xml/doc_builder.rb @@ -66,7 +66,7 @@ def close_el(name) def attributes(attr) return '' if attr.empty? - " #{attr.map { |key, value| "#{key}=#{escape(value, :attr)}" }.join(' ')}" + " #{attr.map { |key, value| "#{key}=#{escape(value.to_s, :attr)}" }.join(' ')}" end def escape(string, text_or_attr) diff --git a/gems/smithy-xml/lib/smithy-xml/parser/frame.rb b/gems/smithy-xml/lib/smithy-xml/parser/frame.rb index 21db358a4..161464e49 100644 --- a/gems/smithy-xml/lib/smithy-xml/parser/frame.rb +++ b/gems/smithy-xml/lib/smithy-xml/parser/frame.rb @@ -243,8 +243,8 @@ def initialize(xml_name, parent, ref, result = nil) def child_frame(xml_name) if (@member = @members[xml_name]) Frame.new(xml_name, self, @member[:ref]) - # elsif @ref.shape.union - # UnknownMemberFrame.new(xml_name, self, nil, @result) + elsif @ref.shape.is_a?(UnionShape) + UnknownMemberFrame.new(xml_name, self, nil, @result) else NullFrame.new(xml_name, self) end @@ -258,34 +258,17 @@ def consume_child_frame(child) # rubocop:disable Metrics/AbcSize when FlatListFrame @result[@member[:name]] ||= [] @result[@member[:name]] << child.result - # when UnknownMemberFrame - # @result[:unknown] = { 'name' => child.path.last, 'value' => child.result } + when UnknownMemberFrame + @result[:unknown] = { child.path.last => child.result } when NullFrame # do nothing - else - @result[@member[:name]] = child.result + else @result[@member[:name]] = child.result end - - # if @ref.shape.union - # # a union may only have one member set - # # convert to the union subclass - # # The default Struct created will have defaults set for all values - # # This also sets only one of the values leaving everything else nil - # # as required for unions - # set_member_name = @member ? @member[:name] : :unknown - # member_subclass = @ref.shape.member_subclass(set_member_name).new - # member_subclass[set_member_name] = @result[set_member_name] - # @result = member_subclass - # end end private def xml_name(ref) - ref.traits['smithy.api#xmlName'] || ref.member_name - end - - def flattened_list?(ref) - ref.shape.is_a?(ListShape) && ref.traits.key?('smithy.api#xmlFlattened') + ref.traits['smithy.api#xmlName'] || ref.location_name end end diff --git a/gems/smithy-xml/lib/smithy-xml/parser/nokogiri_engine.rb b/gems/smithy-xml/lib/smithy-xml/parser/nokogiri_engine.rb index d5e6b2ee2..c73bf4e01 100644 --- a/gems/smithy-xml/lib/smithy-xml/parser/nokogiri_engine.rb +++ b/gems/smithy-xml/lib/smithy-xml/parser/nokogiri_engine.rb @@ -19,6 +19,7 @@ def xmldecl(*_ignored); end def start_document; end def end_document; end def comment(*_ignored); end + def cdata_block(*_ignored); end def start_element_namespace(name, attrs = [], *_ignored) @stack.start_element(name) diff --git a/gems/smithy-xml/spec/smithy-xml/builder_spec.rb b/gems/smithy-xml/spec/smithy-xml/builder_spec.rb new file mode 100644 index 000000000..ff78c8bdd --- /dev/null +++ b/gems/smithy-xml/spec/smithy-xml/builder_spec.rb @@ -0,0 +1,269 @@ +# frozen_string_literal: true + +require_relative '../spec_helper' + +require 'rexml' + +module Smithy + module Xml + describe Builder do + let(:shapes) { SchemaHelper.sample_shapes } + let(:sample_schema) { SchemaHelper.sample_schema(shapes: shapes) } + let(:structure_shape) { sample_schema.const_get(:Structure) } + + def inline(xml) + xml.gsub(/>\n\s*<').strip + end + + it 'returns an empty frame when given a unit shape' do + ref = Schema::Shapes::ShapeRef.new(shape: Schema::Shapes::Prelude::Unit) + expect(subject.build(ref, '')).to eq('') + end + + context 'structures' do + before { allow(Time).to receive(:at).and_return(time) } + let(:time) { Time.now } + let(:data) do + { + big_decimal: 0.0, + big_integer: 0, + blob: 'blob', + boolean: false, + byte: 0, + double: 0.0, + enum: 'enum', + float: 0.0, + int_enum: 0, + integer: 0, + list: [], + long: 0, + map: {}, + short: 0, + streaming_blob: 'streaming blob', + string: 'string', + structure_list: [], + structure_map: {}, + timestamp: time, + union: { string: 'string' } + } + end + let(:expected) do + { + 'bigDecimal' => 0.0, + 'bigInteger' => 0, + 'blob' => 'YmxvYg==', + 'boolean' => false, + 'byte' => 0, + 'double' => 0.0, + 'enum' => 'enum', + 'float' => 0.0, + 'intEnum' => 0, + 'integer' => 0, + 'list' => [], + 'long' => 0, + 'map' => {}, + 'short' => 0, + 'streamingBlob' => 'c3RyZWFtaW5nIGJsb2I=', + 'string' => 'string', + 'structureList' => [], + 'structureMap' => {}, + 'timestamp' => time.to_i, + 'union' => { 'string' => 'string' } + } + end + let(:xml) do + <<~XML + + 0.0 + 0 + YmxvYg== + false + 0 + 0.0 + enum + 0.0 + 0 + 0 + + 0 + + 0 + c3RyZWFtaW5nIGJsb2I= + string + + 0.0 + 0 + YmxvYg== + false + 0 + 0.0 + enum + 0.0 + 0 + 0 + + 0 + + 0 + c3RyZWFtaW5nIGJsb2I= + string + + + #{time.utc.iso8601} + + string + + + + + #{time.utc.iso8601} + + string + + + XML + end + + it 'builds structures as a type' do + type = structure_shape.type.new(data.merge(structure: data)) + bytes = subject.build(structure_shape, type) + expect(bytes).to eq(inline(xml)) + end + + it 'builds structures as a hash' do + bytes = subject.build(structure_shape, data.merge(structure: data)) + expect(bytes).to eq(inline(xml)) + end + + it 'builds structures with xmlName' do + shapes['smithy.ruby.tests#Structure']['members']['string'] = { + 'target' => 'smithy.api#String', + 'traits' => { 'smithy.api#xmlName' => 'NewString' } + } + data = { string: 'string' } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('string') + end + + it 'builds structures with xmlNamespace' do + shapes['smithy.ruby.tests#Structure']['traits'] = { + 'smithy.api#xmlNamespace' => { 'uri' => 'http://example.com/ns' } + } + data = { string: 'string' } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('') + end + + it 'builds structures with xmlAttributes' do + shapes['smithy.ruby.tests#Structure']['members']['string']['traits'] = { + 'smithy.api#xmlAttribute' => {} + } + data = { string: 'string' } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('') + end + end + + context 'unions' do + it 'builds unions as a type' do + union = structure_shape.member(:union).shape.member_type(:string).new(string: 'string') + type = structure_shape.type.new(union: union) + bytes = subject.build(structure_shape, type) + expect(bytes).to include('string') + end + + it 'builds unions as a hash' do + data = { union: { string: 'string' } } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('string') + end + + it 'builds union unit members as a type' do + union = structure_shape.member(:union).shape.member_type(:unit).new(unit: Schema::EmptyStructure.new) + type = structure_shape.type.new(union: union) + bytes = subject.build(structure_shape, type) + expect(bytes).to include('') + end + + it 'builds union unit members as a hash' do + data = { union: { unit: {} } } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('') + end + + it 'builds a nil union' do + data = { union: nil } + bytes = subject.build(structure_shape, data) + expect(bytes).to eq('') + end + + it 'builds union members with xmlName' do + shapes['smithy.ruby.tests#Union']['members']['string'] = { + 'target' => 'smithy.api#String', + 'traits' => { 'smithy.api#xmlName' => 'NewString' } + } + data = { union: { string: 'string' } } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('string') + end + end + + context 'lists' do + it 'builds lists' do + data = { list: ['string'] } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('string') + end + + it 'builds lists with nil values' do + data = { list: [nil] } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('') + end + end + + context 'maps' do + it 'builds maps' do + data = { map: { 'key' => 'value' } } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('keyvalue') + end + + it 'builds maps with nil values' do + data = { map: { 'key' => nil } } + bytes = subject.build(structure_shape, data) + expect(bytes).to include('key') + end + end + + context 'timestamps' do + it 'builds date-time format by default' do + time = Time.now.utc + data = { timestamp: time } + bytes = subject.build(structure_shape, data) + expect(bytes).to include("#{time.utc.iso8601}") + end + + it 'builds epoch seconds format' do + time = Time.now + shapes['smithy.ruby.tests#Structure']['members']['timestamp']['traits'] = { + 'smithy.api#timestampFormat' => 'epoch-seconds' + } + data = { timestamp: time } + bytes = subject.build(structure_shape, data) + expect(bytes).to include("#{time.to_i}") + end + + it 'builds http-date format' do + time = Time.now.utc + shapes['smithy.ruby.tests#Structure']['members']['timestamp']['traits'] = { + 'smithy.api#timestampFormat' => 'http-date' + } + data = { timestamp: time } + bytes = subject.build(structure_shape, data) + expect(bytes).to include("#{time.httpdate}") + end + end + end + end +end diff --git a/gems/smithy-xml/spec/smithy-xml/parser_spec.rb b/gems/smithy-xml/spec/smithy-xml/parser_spec.rb new file mode 100644 index 000000000..c902aa669 --- /dev/null +++ b/gems/smithy-xml/spec/smithy-xml/parser_spec.rb @@ -0,0 +1,292 @@ +# frozen_string_literal: true + +require_relative '../spec_helper' + +module Smithy + module Xml + describe Parser do + let(:shapes) { SchemaHelper.sample_shapes } + let(:sample_schema) { SchemaHelper.sample_schema(shapes: shapes) } + let(:structure_shape) { sample_schema.const_get(:Structure) } + + it 'returns an empty structure when given a unit shape' do + expect(subject.parse(Schema::Shapes::Prelude::Unit, '')).to be_a(Schema::EmptyStructure) + end + + context 'structures' do + before { allow(Time).to receive(:at).and_return(time) } + let(:time) { Time.now } + let(:data) do + { + 'bigDecimal' => 0.0, + 'bigInteger' => 0, + 'blob' => 'YmxvYg==', + 'boolean' => false, + 'byte' => 0, + 'double' => 0.0, + 'enum' => 'enum', + 'float' => 0.0, + 'intEnum' => 0, + 'integer' => 0, + 'list' => [], + 'long' => 0, + 'map' => {}, + 'short' => 0, + 'streamingBlob' => 'c3RyZWFtaW5nIGJsb2I=', + 'string' => 'string', + 'structureList' => [], + 'structureMap' => {}, + 'timestamp' => time, + 'union' => { 'string' => 'string' } + } + end + let(:expected) do + { + big_decimal: 0.0, + big_integer: 0, + blob: 'blob', + boolean: false, + byte: 0, + double: 0.0, + enum: 'enum', + float: 0.0, + int_enum: 0, + integer: 0, + list: [], + long: 0, + map: {}, + short: 0, + streaming_blob: 'streaming blob', + string: 'string', + structure_list: [], + structure_map: {}, + timestamp: time, + union: { string: 'string' } + } + end + + it 'parses structures' do + bytes = <<~XML + + 0.0 + 0 + YmxvYg== + false + 0 + 0.0 + enum + 0.0 + 0 + 0 + + 0 + + 0 + c3RyZWFtaW5nIGJsb2I= + string + + + #{time.to_i} + + string + + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(expected) + end + + it 'parses structures with xmlName' do + shapes['smithy.ruby.tests#Structure']['members']['string'] = { + 'target' => 'smithy.api#String', + 'traits' => { 'smithy.api#xmlName' => 'NewString' } + } + bytes = <<~XML + + string + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(string: 'string') + end + + it 'parses structures with xmlAttribute' do + shapes['smithy.ruby.tests#Structure']['members']['string'] = { + 'target' => 'smithy.api#String', + 'traits' => { 'smithy.api#xmlAttribute' => true } + } + bytes = <<~XML + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(string: 'string') + end + end + + context 'unions' do + it 'parses unions' do + bytes = <<~XML + + + string + + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(union: { string: 'string' }) + end + + it 'parses unit members' do + bytes = <<~XML + + + + + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(union: { unit: {} }) + end + + it 'parses nil unions' do + bytes = <<~XML + + + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(union: {}) + end + + it 'parses unknown members' do + bytes = <<~XML + + + someValue + + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(union: { unknown: { 'someThing' => 'someValue' } }) + end + end + + context 'lists' do + it 'parses lists' do + bytes = <<~XML + + + string + + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(list: ['string']) + end + + it 'parses lists with nil values' do + bytes = <<~XML + + + + + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(list: ['']) + end + end + + context 'maps' do + it 'parses maps' do + bytes = <<~XML + + + + key + value + + + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(map: { 'key' => 'value' }) + end + + it 'parses maps with nil values' do + bytes = <<~XML + + + + key + + + + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(map: { 'key' => '' }) + end + end + + context 'floats' do + it 'parses infinity' do + bytes = <<~XML + + Infinity + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(float: Float::INFINITY) + end + + it 'parses negative infinity' do + bytes = <<~XML + + -Infinity + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(float: -Float::INFINITY) + end + + it 'parses NaN' do + bytes = <<~XML + + NaN + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(float: Float::NAN) + end + end + + context 'timestamps' do + before { allow(Time).to receive(:at).and_return(time) } + let(:time) { Time.now } + + it 'parses epoch seconds' do + bytes = <<~XML + + #{time.to_i} + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(timestamp: time) + end + + it 'parses date-time format' do + bytes = <<~XML + + #{time.utc.iso8601} + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(timestamp: time) + end + + it 'parses http-date format' do + bytes = <<~XML + + #{time.utc.httpdate} + + XML + expect(subject.parse(structure_shape, bytes).to_h).to eq(timestamp: time) + end + + it 'handles unrecognized timestamp formats' do + bytes = <<~XML + + unrecognized format + + XML + expect { subject.parse(structure_shape, bytes) }.to raise_error(/unhandled timestamp format/) + end + end + end + end +end diff --git a/gems/smithy/lib/smithy/templates/client/protocol_spec.erb b/gems/smithy/lib/smithy/templates/client/protocol_spec.erb index c4cbf6fdb..a5eaf0161 100644 --- a/gems/smithy/lib/smithy/templates/client/protocol_spec.erb +++ b/gems/smithy/lib/smithy/templates/client/protocol_spec.erb @@ -15,7 +15,7 @@ module <%= module_name %> <% test.docstrings.each do |line| -%> # <%= line %> <% end -%> -<% if test.skip? -%> +<% if test.skip?('request') -%> it '<%= test['id'] %>', skip: '<%= test.skip_reason %>' do <% else -%> it '<%= test['id'] %>' do @@ -73,7 +73,7 @@ module <%= module_name %> <% test.docstrings.each do |line| -%> # <%= line %> <% end -%> -<% if test.skip? -%> +<% if test.skip?('response') -%> it '<%= test['id'] %>', skip: '<%= test.skip_reason %>' do <% else -%> it '<%= test['id'] %>' do @@ -92,7 +92,7 @@ module <%= module_name %> describe 'response stubs' do <% operation_tests.response_tests.each do |test| -%> -<% if test.skip? -%> +<% if test.skip?('stub') -%> it '<%= test['id'] %>', skip: '<%= test.skip_reason %>' do <% else -%> it '<%= test['id'] %>' do @@ -115,7 +115,7 @@ module <%= module_name %> <% test.docstrings.each do |line| -%> # <%= line %> <% end -%> -<% if test.skip? -%> +<% if test.skip?('response') -%> it '<%= test['id'] %>: <%= test.error_name %>', skip: '<%= test.skip_reason %>' do <% else -%> it '<%= test['id'] %>: <%= test.error_name %>' do @@ -134,7 +134,7 @@ module <%= module_name %> describe 'response error stubs' do <% operation_tests.error_tests.each do |test| -%> -<% if test.skip? -%> +<% if test.skip?('stub') -%> it '<%= test['id'] %>: <%= test.error_name %>', skip: '<%= test.skip_reason %>' do <% else -%> it '<%= test['id'] %>: <%= test.error_name %>' do diff --git a/gems/smithy/lib/smithy/views/client/protocol_spec.rb b/gems/smithy/lib/smithy/views/client/protocol_spec.rb index 937a11c46..fe40b69b0 100644 --- a/gems/smithy/lib/smithy/views/client/protocol_spec.rb +++ b/gems/smithy/lib/smithy/views/client/protocol_spec.rb @@ -119,11 +119,11 @@ def docstrings @test_case.fetch('documentation', '').split("\n") end - def skip? + def skip?(type) @operation .fetch('traits', {}) .fetch('smithy.ruby#skipTests', []) - .any? { |skip| skip['id'] == @test_case['id'] } + .any? { |skip| skip['id'] == @test_case['id'] && skip['type'] == type } end def skip_reason @@ -156,6 +156,8 @@ def body_expect "expect(Smithy::Json.load(request.body.read)).to eq(Smithy::Json.load('#{@test_case['body']}'))" when 'application/x-www-form-urlencoded' "expect(CGI.parse(request.body.read)).to eq(CGI.parse('#{@test_case['body']}'))" + when 'application/xml' + "expect(request.body.read).to eq('#{@test_case['body'].gsub(/>\n\s*<').strip}')" else "expect(request.body.read).to eq('#{@test_case['body']}')" end diff --git a/gems/smithy/lib/smithy/views/client/schema.rb b/gems/smithy/lib/smithy/views/client/schema.rb index ca524c890..4ef5c040e 100644 --- a/gems/smithy/lib/smithy/views/client/schema.rb +++ b/gems/smithy/lib/smithy/views/client/schema.rb @@ -91,17 +91,14 @@ class OperationShape def initialize(service, id, shape) _, @service = service.first @id = id - @input = ShapeRef.new(@service, nil, shape['input']) - @output = ShapeRef.new(@service, nil, shape['output']) - @errors = build_errors(@service['errors'] || []).concat(build_errors(shape['errors'] || [])) + @name = (@service.dig('rename', @id) || Model::Shape.name(@id)).camelize + @input = build_input(shape['input']) + @output = build_output(shape['output']) + @errors = build_errors(shape.fetch('errors', [])) @traits = shape.fetch('traits', {}) end - attr_reader :id, :input, :output, :errors - - def name - Model::Shape.name(@id) - end + attr_reader :id, :name, :input, :output, :errors def traits @traits.except(*OMITTED_TRAITS) @@ -112,13 +109,22 @@ def paginated? end def paginator - "Paginators::#{Model::Shape.name(@id)}.new" + "Paginators::#{@name}.new" end private + def build_input(input) + ShapeRef.new(@service, nil, input) + end + + def build_output(output) + ShapeRef.new(@service, nil, output) + end + def build_errors(errors) - errors.map { |shape_ref| ShapeRef.new(@service, nil, shape_ref) } + errors = Set.new(@service.fetch('errors', [])).merge(errors) + errors.map { |error| ShapeRef.new(@service, nil, error) } end end @@ -198,7 +204,7 @@ def http_payload private def build_shape_refs(members) - members.map { |name, shape_ref| ShapeRef.new(@service, name, shape_ref) } + members.map { |name, member| ShapeRef.new(@service, name, member) } end end @@ -230,7 +236,7 @@ def initialize(service, id, shape) private def build_shape_refs(members) - members.map { |name, shape_ref| ShapeRef.new(@service, name, shape_ref) } + members.map { |name, member| ShapeRef.new(@service, name, member) } end end @@ -275,7 +281,7 @@ def union_type(shape_ref) private def build_shape_refs(members) - members.map { |name, shape_ref| ShapeRef.new(@service, name, shape_ref) } + members.map { |name, member| ShapeRef.new(@service, name, member) } end end @@ -310,10 +316,10 @@ class ShapeRef 'smithy.api#Unit' => 'Prelude::Unit' }.freeze - def initialize(service, member_name, shape_ref) + def initialize(service, location_name, shape_ref) @service = service - @name = member_name.underscore if member_name - @member_name = member_name + @name = location_name.underscore if location_name + @location_name = location_name @shape = shape(shape_ref['target']) @traits = shape_ref.fetch('traits', {}) end @@ -322,7 +328,7 @@ def initialize(service, member_name, shape_ref) def initializer options_str = "shape: #{@shape}" - options_str += ", member_name: '#{@member_name}'" if @member_name + options_str += ", location_name: '#{@location_name}'" if @location_name options_str += ", traits: #{@traits}" unless @traits.empty? "Smithy::Schema::Shapes::ShapeRef.new(#{options_str})" end diff --git a/gems/smithy/model/skip_tests.smithy b/gems/smithy/model/skip_tests.smithy index 539e66e0f..dfd4b0b61 100644 --- a/gems/smithy/model/skip_tests.smithy +++ b/gems/smithy/model/skip_tests.smithy @@ -20,4 +20,7 @@ enum TestType { @enumValue("response") RESPONSE + + @enumValue("stub") + STUB } diff --git a/projections/shapes/lib/shapes/schema.rb b/projections/shapes/lib/shapes/schema.rb index fb511885d..5b792d37c 100644 --- a/projections/shapes/lib/shapes/schema.rb +++ b/projections/shapes/lib/shapes/schema.rb @@ -28,56 +28,56 @@ module Schema Timestamp = Smithy::Schema::Shapes::TimestampShape.new(id: 'smithy.ruby.tests#Timestamp', name: 'Timestamp', traits: {"smithy.ruby.tests#shape" => {}}) Union = Smithy::Schema::Shapes::UnionShape.new(id: 'smithy.ruby.tests#Union', name: 'Union', traits: {"smithy.ruby.tests#shape" => {}}) - Enum.add_member(:foo, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Unit, member_name: 'FOO', traits: {"smithy.api#enumValue" => "bar"})) - IntEnum.add_member(:baz, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Unit, member_name: 'BAZ', traits: {"smithy.api#enumValue" => 1})) + Enum.add_member(:foo, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Unit, location_name: 'FOO', traits: {"smithy.api#enumValue" => "bar"})) + IntEnum.add_member(:baz, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Unit, location_name: 'BAZ', traits: {"smithy.api#enumValue" => 1})) List.member = Smithy::Schema::Shapes::ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) Map.key = Smithy::Schema::Shapes::ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) Map.value = Smithy::Schema::Shapes::ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) - OperationInput.add_member(:blob, Smithy::Schema::Shapes::ShapeRef.new(shape: Blob, member_name: 'blob')) - OperationInput.add_member(:boolean, Smithy::Schema::Shapes::ShapeRef.new(shape: Boolean, member_name: 'boolean')) - OperationInput.add_member(:string, Smithy::Schema::Shapes::ShapeRef.new(shape: String, member_name: 'string')) - OperationInput.add_member(:byte, Smithy::Schema::Shapes::ShapeRef.new(shape: Byte, member_name: 'byte')) - OperationInput.add_member(:short, Smithy::Schema::Shapes::ShapeRef.new(shape: Short, member_name: 'short')) - OperationInput.add_member(:integer, Smithy::Schema::Shapes::ShapeRef.new(shape: Integer, member_name: 'integer')) - OperationInput.add_member(:long, Smithy::Schema::Shapes::ShapeRef.new(shape: Long, member_name: 'long')) - OperationInput.add_member(:float, Smithy::Schema::Shapes::ShapeRef.new(shape: Float, member_name: 'float')) - OperationInput.add_member(:double, Smithy::Schema::Shapes::ShapeRef.new(shape: Double, member_name: 'double')) - OperationInput.add_member(:big_integer, Smithy::Schema::Shapes::ShapeRef.new(shape: BigInteger, member_name: 'bigInteger')) - OperationInput.add_member(:big_decimal, Smithy::Schema::Shapes::ShapeRef.new(shape: BigDecimal, member_name: 'bigDecimal')) - OperationInput.add_member(:timestamp, Smithy::Schema::Shapes::ShapeRef.new(shape: Timestamp, member_name: 'timestamp')) - OperationInput.add_member(:document, Smithy::Schema::Shapes::ShapeRef.new(shape: Document, member_name: 'document')) - OperationInput.add_member(:enum, Smithy::Schema::Shapes::ShapeRef.new(shape: Enum, member_name: 'enum')) - OperationInput.add_member(:int_enum, Smithy::Schema::Shapes::ShapeRef.new(shape: IntEnum, member_name: 'intEnum')) - OperationInput.add_member(:list, Smithy::Schema::Shapes::ShapeRef.new(shape: List, member_name: 'list')) - OperationInput.add_member(:map, Smithy::Schema::Shapes::ShapeRef.new(shape: Map, member_name: 'map')) - OperationInput.add_member(:structure, Smithy::Schema::Shapes::ShapeRef.new(shape: Structure, member_name: 'structure')) - OperationInput.add_member(:union, Smithy::Schema::Shapes::ShapeRef.new(shape: Union, member_name: 'union')) + OperationInput.add_member(:blob, Smithy::Schema::Shapes::ShapeRef.new(shape: Blob, location_name: 'blob')) + OperationInput.add_member(:boolean, Smithy::Schema::Shapes::ShapeRef.new(shape: Boolean, location_name: 'boolean')) + OperationInput.add_member(:string, Smithy::Schema::Shapes::ShapeRef.new(shape: String, location_name: 'string')) + OperationInput.add_member(:byte, Smithy::Schema::Shapes::ShapeRef.new(shape: Byte, location_name: 'byte')) + OperationInput.add_member(:short, Smithy::Schema::Shapes::ShapeRef.new(shape: Short, location_name: 'short')) + OperationInput.add_member(:integer, Smithy::Schema::Shapes::ShapeRef.new(shape: Integer, location_name: 'integer')) + OperationInput.add_member(:long, Smithy::Schema::Shapes::ShapeRef.new(shape: Long, location_name: 'long')) + OperationInput.add_member(:float, Smithy::Schema::Shapes::ShapeRef.new(shape: Float, location_name: 'float')) + OperationInput.add_member(:double, Smithy::Schema::Shapes::ShapeRef.new(shape: Double, location_name: 'double')) + OperationInput.add_member(:big_integer, Smithy::Schema::Shapes::ShapeRef.new(shape: BigInteger, location_name: 'bigInteger')) + OperationInput.add_member(:big_decimal, Smithy::Schema::Shapes::ShapeRef.new(shape: BigDecimal, location_name: 'bigDecimal')) + OperationInput.add_member(:timestamp, Smithy::Schema::Shapes::ShapeRef.new(shape: Timestamp, location_name: 'timestamp')) + OperationInput.add_member(:document, Smithy::Schema::Shapes::ShapeRef.new(shape: Document, location_name: 'document')) + OperationInput.add_member(:enum, Smithy::Schema::Shapes::ShapeRef.new(shape: Enum, location_name: 'enum')) + OperationInput.add_member(:int_enum, Smithy::Schema::Shapes::ShapeRef.new(shape: IntEnum, location_name: 'intEnum')) + OperationInput.add_member(:list, Smithy::Schema::Shapes::ShapeRef.new(shape: List, location_name: 'list')) + OperationInput.add_member(:map, Smithy::Schema::Shapes::ShapeRef.new(shape: Map, location_name: 'map')) + OperationInput.add_member(:structure, Smithy::Schema::Shapes::ShapeRef.new(shape: Structure, location_name: 'structure')) + OperationInput.add_member(:union, Smithy::Schema::Shapes::ShapeRef.new(shape: Union, location_name: 'union')) OperationInput.type = Types::OperationInput - OperationOutput.add_member(:blob, Smithy::Schema::Shapes::ShapeRef.new(shape: Blob, member_name: 'blob')) - OperationOutput.add_member(:boolean, Smithy::Schema::Shapes::ShapeRef.new(shape: Boolean, member_name: 'boolean')) - OperationOutput.add_member(:string, Smithy::Schema::Shapes::ShapeRef.new(shape: String, member_name: 'string')) - OperationOutput.add_member(:byte, Smithy::Schema::Shapes::ShapeRef.new(shape: Byte, member_name: 'byte')) - OperationOutput.add_member(:short, Smithy::Schema::Shapes::ShapeRef.new(shape: Short, member_name: 'short')) - OperationOutput.add_member(:integer, Smithy::Schema::Shapes::ShapeRef.new(shape: Integer, member_name: 'integer')) - OperationOutput.add_member(:long, Smithy::Schema::Shapes::ShapeRef.new(shape: Long, member_name: 'long')) - OperationOutput.add_member(:float, Smithy::Schema::Shapes::ShapeRef.new(shape: Float, member_name: 'float')) - OperationOutput.add_member(:double, Smithy::Schema::Shapes::ShapeRef.new(shape: Double, member_name: 'double')) - OperationOutput.add_member(:big_integer, Smithy::Schema::Shapes::ShapeRef.new(shape: BigInteger, member_name: 'bigInteger')) - OperationOutput.add_member(:big_decimal, Smithy::Schema::Shapes::ShapeRef.new(shape: BigDecimal, member_name: 'bigDecimal')) - OperationOutput.add_member(:timestamp, Smithy::Schema::Shapes::ShapeRef.new(shape: Timestamp, member_name: 'timestamp')) - OperationOutput.add_member(:document, Smithy::Schema::Shapes::ShapeRef.new(shape: Document, member_name: 'document')) - OperationOutput.add_member(:enum, Smithy::Schema::Shapes::ShapeRef.new(shape: Enum, member_name: 'enum')) - OperationOutput.add_member(:int_enum, Smithy::Schema::Shapes::ShapeRef.new(shape: IntEnum, member_name: 'intEnum')) - OperationOutput.add_member(:list, Smithy::Schema::Shapes::ShapeRef.new(shape: List, member_name: 'list')) - OperationOutput.add_member(:map, Smithy::Schema::Shapes::ShapeRef.new(shape: Map, member_name: 'map')) - OperationOutput.add_member(:structure, Smithy::Schema::Shapes::ShapeRef.new(shape: Structure, member_name: 'structure')) - OperationOutput.add_member(:union, Smithy::Schema::Shapes::ShapeRef.new(shape: Union, member_name: 'union')) + OperationOutput.add_member(:blob, Smithy::Schema::Shapes::ShapeRef.new(shape: Blob, location_name: 'blob')) + OperationOutput.add_member(:boolean, Smithy::Schema::Shapes::ShapeRef.new(shape: Boolean, location_name: 'boolean')) + OperationOutput.add_member(:string, Smithy::Schema::Shapes::ShapeRef.new(shape: String, location_name: 'string')) + OperationOutput.add_member(:byte, Smithy::Schema::Shapes::ShapeRef.new(shape: Byte, location_name: 'byte')) + OperationOutput.add_member(:short, Smithy::Schema::Shapes::ShapeRef.new(shape: Short, location_name: 'short')) + OperationOutput.add_member(:integer, Smithy::Schema::Shapes::ShapeRef.new(shape: Integer, location_name: 'integer')) + OperationOutput.add_member(:long, Smithy::Schema::Shapes::ShapeRef.new(shape: Long, location_name: 'long')) + OperationOutput.add_member(:float, Smithy::Schema::Shapes::ShapeRef.new(shape: Float, location_name: 'float')) + OperationOutput.add_member(:double, Smithy::Schema::Shapes::ShapeRef.new(shape: Double, location_name: 'double')) + OperationOutput.add_member(:big_integer, Smithy::Schema::Shapes::ShapeRef.new(shape: BigInteger, location_name: 'bigInteger')) + OperationOutput.add_member(:big_decimal, Smithy::Schema::Shapes::ShapeRef.new(shape: BigDecimal, location_name: 'bigDecimal')) + OperationOutput.add_member(:timestamp, Smithy::Schema::Shapes::ShapeRef.new(shape: Timestamp, location_name: 'timestamp')) + OperationOutput.add_member(:document, Smithy::Schema::Shapes::ShapeRef.new(shape: Document, location_name: 'document')) + OperationOutput.add_member(:enum, Smithy::Schema::Shapes::ShapeRef.new(shape: Enum, location_name: 'enum')) + OperationOutput.add_member(:int_enum, Smithy::Schema::Shapes::ShapeRef.new(shape: IntEnum, location_name: 'intEnum')) + OperationOutput.add_member(:list, Smithy::Schema::Shapes::ShapeRef.new(shape: List, location_name: 'list')) + OperationOutput.add_member(:map, Smithy::Schema::Shapes::ShapeRef.new(shape: Map, location_name: 'map')) + OperationOutput.add_member(:structure, Smithy::Schema::Shapes::ShapeRef.new(shape: Structure, location_name: 'structure')) + OperationOutput.add_member(:union, Smithy::Schema::Shapes::ShapeRef.new(shape: Union, location_name: 'union')) OperationOutput.type = Types::OperationOutput - Structure.add_member(:member, Smithy::Schema::Shapes::ShapeRef.new(shape: String, member_name: 'member', traits: {"smithy.ruby.tests#shape" => {}})) + Structure.add_member(:member, Smithy::Schema::Shapes::ShapeRef.new(shape: String, location_name: 'member', traits: {"smithy.ruby.tests#shape" => {}})) Structure.type = Types::Structure - Union.add_member(:string, Types::Union::String, Smithy::Schema::Shapes::ShapeRef.new(shape: String, member_name: 'string', traits: {"smithy.ruby.tests#shape" => {}})) - Union.add_member(:structure, Types::Union::Structure, Smithy::Schema::Shapes::ShapeRef.new(shape: Structure, member_name: 'structure', traits: {"smithy.ruby.tests#shape" => {}})) - Union.add_member(:unit, Types::Union::Unit, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Unit, member_name: 'unit', traits: {"smithy.ruby.tests#shape" => {}})) + Union.add_member(:string, Types::Union::String, Smithy::Schema::Shapes::ShapeRef.new(shape: String, location_name: 'string', traits: {"smithy.ruby.tests#shape" => {}})) + Union.add_member(:structure, Types::Union::Structure, Smithy::Schema::Shapes::ShapeRef.new(shape: Structure, location_name: 'structure', traits: {"smithy.ruby.tests#shape" => {}})) + Union.add_member(:unit, Types::Union::Unit, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Unit, location_name: 'unit', traits: {"smithy.ruby.tests#shape" => {}})) Union.add_member(:unknown, Types::Union::Unknown, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Unit)) Union.type = Types::Union diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index 9a372e40e..d6904e350 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -19,31 +19,31 @@ module Schema ListCitiesOutput = Smithy::Schema::Shapes::StructureShape.new(id: 'example.weather#ListCitiesOutput', name: 'ListCitiesOutput') NoSuchResource = Smithy::Schema::Shapes::StructureShape.new(id: 'example.weather#NoSuchResource', name: 'NoSuchResource', traits: {"smithy.api#error" => "client"}) - CityCoordinates.add_member(:latitude, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Float, member_name: 'latitude', traits: {"smithy.api#required" => {}})) - CityCoordinates.add_member(:longitude, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Float, member_name: 'longitude', traits: {"smithy.api#required" => {}})) + CityCoordinates.add_member(:latitude, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Float, location_name: 'latitude', traits: {"smithy.api#required" => {}})) + CityCoordinates.add_member(:longitude, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Float, location_name: 'longitude', traits: {"smithy.api#required" => {}})) CityCoordinates.type = Types::CityCoordinates CitySummaries.member = Smithy::Schema::Shapes::ShapeRef.new(shape: CitySummary) - CitySummary.add_member(:city_id, Smithy::Schema::Shapes::ShapeRef.new(shape: CityId, member_name: 'cityId', traits: {"smithy.api#required" => {}})) - CitySummary.add_member(:name, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, member_name: 'name', traits: {"smithy.api#required" => {}})) + CitySummary.add_member(:city_id, Smithy::Schema::Shapes::ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required" => {}})) + CitySummary.add_member(:name, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, location_name: 'name', traits: {"smithy.api#required" => {}})) CitySummary.type = Types::CitySummary - GetCityInput.add_member(:city_id, Smithy::Schema::Shapes::ShapeRef.new(shape: CityId, member_name: 'cityId', traits: {"smithy.api#required" => {}})) + GetCityInput.add_member(:city_id, Smithy::Schema::Shapes::ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required" => {}})) GetCityInput.type = Types::GetCityInput - GetCityOutput.add_member(:name, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, member_name: 'name', traits: {"smithy.api#notProperty" => {}, "smithy.api#required" => {}})) - GetCityOutput.add_member(:coordinates, Smithy::Schema::Shapes::ShapeRef.new(shape: CityCoordinates, member_name: 'coordinates', traits: {"smithy.api#required" => {}})) + GetCityOutput.add_member(:name, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, location_name: 'name', traits: {"smithy.api#notProperty" => {}, "smithy.api#required" => {}})) + GetCityOutput.add_member(:coordinates, Smithy::Schema::Shapes::ShapeRef.new(shape: CityCoordinates, location_name: 'coordinates', traits: {"smithy.api#required" => {}})) GetCityOutput.type = Types::GetCityOutput - GetCurrentTimeOutput.add_member(:time, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Timestamp, member_name: 'time', traits: {"smithy.api#required" => {}})) + GetCurrentTimeOutput.add_member(:time, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Timestamp, location_name: 'time', traits: {"smithy.api#required" => {}})) GetCurrentTimeOutput.type = Types::GetCurrentTimeOutput - GetForecastInput.add_member(:city_id, Smithy::Schema::Shapes::ShapeRef.new(shape: CityId, member_name: 'cityId', traits: {"smithy.api#required" => {}})) + GetForecastInput.add_member(:city_id, Smithy::Schema::Shapes::ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required" => {}})) GetForecastInput.type = Types::GetForecastInput - GetForecastOutput.add_member(:chance_of_rain, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Float, member_name: 'chanceOfRain')) + GetForecastOutput.add_member(:chance_of_rain, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Float, location_name: 'chanceOfRain')) GetForecastOutput.type = Types::GetForecastOutput - ListCitiesInput.add_member(:next_token, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, member_name: 'nextToken')) - ListCitiesInput.add_member(:page_size, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Integer, member_name: 'pageSize')) + ListCitiesInput.add_member(:next_token, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, location_name: 'nextToken')) + ListCitiesInput.add_member(:page_size, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::Integer, location_name: 'pageSize')) ListCitiesInput.type = Types::ListCitiesInput - ListCitiesOutput.add_member(:next_token, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, member_name: 'nextToken')) - ListCitiesOutput.add_member(:items, Smithy::Schema::Shapes::ShapeRef.new(shape: CitySummaries, member_name: 'items', traits: {"smithy.api#required" => {}})) + ListCitiesOutput.add_member(:next_token, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, location_name: 'nextToken')) + ListCitiesOutput.add_member(:items, Smithy::Schema::Shapes::ShapeRef.new(shape: CitySummaries, location_name: 'items', traits: {"smithy.api#required" => {}})) ListCitiesOutput.type = Types::ListCitiesOutput - NoSuchResource.add_member(:resource_type, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, member_name: 'resourceType', traits: {"smithy.api#required" => {}})) + NoSuchResource.add_member(:resource_type, Smithy::Schema::Shapes::ShapeRef.new(shape: Smithy::Schema::Shapes::Prelude::String, location_name: 'resourceType', traits: {"smithy.api#required" => {}})) NoSuchResource.type = Types::NoSuchResource Weather = Smithy::Schema::Shapes::ServiceShape.new do |service|