icss 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. data/.document +5 -0
  2. data/.rspec +3 -0
  3. data/.watchr +20 -0
  4. data/CHANGELOG.textile +8 -0
  5. data/Gemfile +17 -0
  6. data/Gemfile.lock +34 -0
  7. data/LICENSE.textile +20 -0
  8. data/README.textile +19 -0
  9. data/Rakefile +43 -0
  10. data/VERSION +1 -0
  11. data/examples/BulkData.avpr +21 -0
  12. data/examples/complicated.icss.yaml +158 -0
  13. data/examples/interop.avsc +32 -0
  14. data/examples/mail.avpr +20 -0
  15. data/examples/namespace.avpr +28 -0
  16. data/examples/org/apache/avro/ipc/HandshakeRequest.avsc +11 -0
  17. data/examples/org/apache/avro/ipc/HandshakeResponse.avsc +15 -0
  18. data/examples/org/apache/avro/ipc/trace/avroTrace.avdl +64 -0
  19. data/examples/org/apache/avro/ipc/trace/avroTrace.avpr +82 -0
  20. data/examples/org/apache/avro/mapred/tether/InputProtocol.avpr +59 -0
  21. data/examples/org/apache/avro/mapred/tether/OutputProtocol.avpr +75 -0
  22. data/examples/simple.avpr +70 -0
  23. data/examples/weather.avsc +9 -0
  24. data/icss.gemspec +104 -0
  25. data/icss_specification.textile +370 -0
  26. data/init.rb +3 -0
  27. data/lib/icss.rb +19 -0
  28. data/lib/icss/brevity.rb +136 -0
  29. data/lib/icss/code_asset.rb +16 -0
  30. data/lib/icss/core_ext.rb +4 -0
  31. data/lib/icss/data_asset.rb +22 -0
  32. data/lib/icss/message.rb +72 -0
  33. data/lib/icss/old.rb +96 -0
  34. data/lib/icss/protocol.rb +138 -0
  35. data/lib/icss/protocol_set.rb +48 -0
  36. data/lib/icss/sample_message_call.rb +140 -0
  37. data/lib/icss/target.rb +71 -0
  38. data/lib/icss/type.rb +517 -0
  39. data/lib/icss/type/factory.rb +196 -0
  40. data/lib/icss/validations.rb +16 -0
  41. data/lib/icss/view_helper.rb +28 -0
  42. data/spec/icss_spec.rb +7 -0
  43. data/spec/spec_helper.rb +31 -0
  44. metadata +218 -0
@@ -0,0 +1,196 @@
1
+ module Icss
2
+ class MetaType
3
+ include Receiver
4
+
5
+ def initialize *args
6
+ receive! *args unless args.empty?
7
+ end
8
+
9
+ # Returns a string containing an XML representation of its receiver:
10
+ #
11
+ # {"foo" => 1, "bar" => 2}.to_xml
12
+ # # =>
13
+ # # <?xml version="1.0" encoding="UTF-8"?>
14
+ # # <hash>
15
+ # # <foo type="integer">1</foo>
16
+ # # <bar type="integer">2</bar>
17
+ # # </hash>
18
+ #
19
+ # To do so, the method loops over the pairs and builds nodes that depend on
20
+ # the _values_. Given a pair +key+, +value+:
21
+ #
22
+ # * If +value+ is a hash there's a recursive call with +key+ as <tt>:root</tt>.
23
+ #
24
+ # * If +value+ is an array there's a recursive call with +key+ as <tt>:root</tt>,
25
+ # and +key+ singularized as <tt>:children</tt>.
26
+ #
27
+ # * If +value+ is a callable object it must expect one or two arguments. Depending
28
+ # on the arity, the callable is invoked with the +options+ hash as first argument
29
+ # with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. Its
30
+ # return value becomes a new node.
31
+ #
32
+ # * If +value+ responds to +to_xml+ the method is invoked with +key+ as <tt>:root</tt>.
33
+ #
34
+ # * Otherwise, a node with +key+ as tag is created with a string representation of
35
+ # +value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added.
36
+ # Unless the option <tt>:skip_types</tt> exists and is true, an attribute "type" is
37
+ # added as well according to the following mapping:
38
+ #
39
+ # XML_TYPE_NAMES = {
40
+ # "Symbol" => "symbol",
41
+ # "Fixnum" => "integer",
42
+ # "Bignum" => "integer",
43
+ # "BigDecimal" => "decimal",
44
+ # "Float" => "float",
45
+ # "TrueClass" => "boolean",
46
+ # "FalseClass" => "boolean",
47
+ # "Date" => "date",
48
+ # "DateTime" => "datetime",
49
+ # "Time" => "datetime"
50
+ # }
51
+ #
52
+ # By default the root node is "hash", but that's configurable via the <tt>:root</tt> option.
53
+ #
54
+ # The default XML builder is a fresh instance of <tt>Builder::XmlMarkup</tt>. You can
55
+ # configure your own builder with the <tt>:builder</tt> option. The method also accepts
56
+ # options like <tt>:dasherize</tt> and friends, they are forwarded to the builder.
57
+ # Returns a string containing an XML representation of its receiver:
58
+ #
59
+ # {"foo" => 1, "bar" => 2}.to_xml
60
+ # # =>
61
+ # # <?xml version="1.0" encoding="UTF-8"?>
62
+ # # <hash>
63
+ # # <foo type="integer">1</foo>
64
+ # # <bar type="integer">2</bar>
65
+ # # </hash>
66
+ #
67
+ # To do so, the method loops over the pairs and builds nodes that depend on
68
+ # the _values_. Given a pair +key+, +value+:
69
+ #
70
+ # * If +value+ is a hash there's a recursive call with +key+ as <tt>:root</tt>.
71
+ #
72
+ # * If +value+ is an array there's a recursive call with +key+ as <tt>:root</tt>,
73
+ # and +key+ singularized as <tt>:children</tt>.
74
+ #
75
+ # * If +value+ is a callable object it must expect one or two arguments. Depending
76
+ # on the arity, the callable is invoked with the +options+ hash as first argument
77
+ # with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. Its
78
+ # return value becomes a new node.
79
+ #
80
+ # * If +value+ responds to +to_xml+ the method is invoked with +key+ as <tt>:root</tt>.
81
+ #
82
+ # * Otherwise, a node with +key+ as tag is created with a string representation of
83
+ # +value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added.
84
+ # Unless the option <tt>:skip_types</tt> exists and is true, an attribute "type" is
85
+ # added as well according to the following mapping:
86
+ #
87
+ # XML_TYPE_NAMES = {
88
+ # "Symbol" => "symbol",
89
+ # "Fixnum" => "integer",
90
+ # "Bignum" => "integer",
91
+ # "BigDecimal" => "decimal",
92
+ # "Float" => "float",
93
+ # "TrueClass" => "boolean",
94
+ # "FalseClass" => "boolean",
95
+ # "Date" => "date",
96
+ # "DateTime" => "datetime",
97
+ # "Time" => "datetime"
98
+ # }
99
+ #
100
+ # By default the root node is "hash", but that's configurable via the <tt>:root</tt> option.
101
+ #
102
+ # The default XML builder is a fresh instance of <tt>Builder::XmlMarkup</tt>. You can
103
+ # configure your own builder with the <tt>:builder</tt> option. The method also accepts
104
+ # options like <tt>:dasherize</tt> and friends, they are forwarded to the
105
+ #builder.
106
+ #
107
+ def to_xml options={}, &block
108
+ options = options.reverse_merge(:root => self.class.xml_type_name)
109
+ xml_hsh = self.to_hash
110
+ # # remove once microsoft has signed off on this
111
+ # xml_hsh.merge!(:_note => "XML support is experimental, structure may change in future") unless options[:skip_instruct]
112
+ xml_hsh.to_xml(options, &block)
113
+ end
114
+
115
+ def self.xml_type_name
116
+ self.to_s.demodulize.underscore.dasherize
117
+ end
118
+
119
+ def to_json *args
120
+ to_hash.to_json(*args)
121
+ end
122
+ end
123
+
124
+ class RecordType < NamedType
125
+
126
+ def ruby_klass_scope_names
127
+ fullname.split('.').map(&:camelize)
128
+ end
129
+ def ruby_klass_name
130
+ "::" + ruby_klass_scope_names.join('::')
131
+ end
132
+ def ruby_klass_parent
133
+ ("::" + ruby_klass_scope_names[0..-2].join('::')).constantize
134
+ end
135
+
136
+ def ensure_parent_modules!
137
+ ruby_klass_scope_names[0..-2].inject(Object) do |parent_module, module_name|
138
+ new_parent = "::#{parent_module}::#{module_name}".constantize rescue nil
139
+ new_parent ||= parent_module.const_set(module_name.to_sym, Module.new)
140
+ # p [parent_module, new_parent, module_name]
141
+ new_parent
142
+ end
143
+ end
144
+
145
+ def define_klass
146
+ ensure_parent_modules!
147
+ parent_module = ruby_klass_parent
148
+ klass_basename = ruby_klass_scope_names.last.to_sym
149
+ klass = parent_module.const_get(klass_basename) rescue nil
150
+ klass ||= parent_module.const_set(klass_basename, Class.new(::Icss::MetaType))
151
+ klass
152
+ end
153
+
154
+ def ruby_klass
155
+ return @klass if @klass
156
+ klass = define_klass
157
+ decorate_with_receivers(klass)
158
+ decorate_with_conveniences(klass)
159
+ @klass = klass
160
+ end
161
+
162
+ def decorate_with_receivers klass
163
+ fields.each do |field|
164
+ field.define_receiver_on(klass)
165
+ end
166
+ end
167
+
168
+ def decorate_with_conveniences klass
169
+ klass.send :include, Receiver::ActsAsHash
170
+ end
171
+
172
+ end
173
+
174
+ Icss::RecordField.class_eval do
175
+ def define_receiver_on(klass)
176
+ if union? || enum?
177
+ warn "Can't handle union or enum types yet: #{self.inspect}"
178
+ return
179
+ end
180
+ p self if type.nil?
181
+ klass.rcvr_accessor name.to_sym, type.ruby_klass, field_receiver_attrs
182
+ end
183
+
184
+ def field_receiver_attrs
185
+ attrs = {}
186
+ (self.class.receiver_attr_names - [:name, :type]).each do |attr|
187
+ val = attr_set?(attr) && self.send(attr) or next
188
+ attrs[attr] = val
189
+ end
190
+ case self.type
191
+ when Icss::ArrayType then attrs[:of] = self.type.items.ruby_klass
192
+ end
193
+ attrs
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,16 @@
1
+ module Icss
2
+ module Validations
3
+
4
+ # An avro name must
5
+ # * start with [A-Za-z_]
6
+ # * subsequently contain only [A-Za-z0-9_]
7
+ def validate_name
8
+ (name =~ /\A[A-Za-z_]\w*\z/) or raise "An avro name must start with [A-Za-z_] and contain only [A-Za-z0-9_]; have #{name}. A namespace is the dot-separated sequence of such names."
9
+ end
10
+
11
+ def validate_namespace
12
+ (name =~ /\A([A-Za-z_]\w*\.?)+\z/) or raise "An avro name must start with [A-Za-z_] and contain only [A-Za-z0-9_]; have #{name}. A namespace is the dot-separated sequence of such names."
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ module Icss
2
+ Message.class_eval do
3
+
4
+ def query_string
5
+ fields = request.first.type.fields rescue nil ; return unless fields
6
+ fields.map do |field|
7
+ "#{field.name}=#{first_sample_request_param[field.name.to_s]}"
8
+ end.join("&")
9
+ end
10
+
11
+ def api_url
12
+ # all calls accept xml or json
13
+ "http://api.infochimps.com/#{path}?#{query_string}"
14
+ end
15
+ end
16
+
17
+ RecordField.class_eval do
18
+ def title
19
+ return "!!missing!!" if type.blank?
20
+ # case type
21
+ # when ArrayType then "array of #{type.title} #{type.to_hash.inspect}"
22
+ # else type.title
23
+ # end
24
+ type.title
25
+ end
26
+ end
27
+
28
+ end
data/spec/icss_spec.rb ADDED
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Icss" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1,31 @@
1
+ require 'spork'
2
+ require 'rspec'
3
+
4
+ Spork.prefork do
5
+ # This code is run only once when the spork server is started
6
+
7
+ ENV["RACK_ENV"] ||= 'test'
8
+ RACK_ENV = ENV["RACK_ENV"] unless defined?(RACK_ENV)
9
+
10
+ require File.join(File.dirname(__FILE__), '../lib/boot')
11
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
12
+
13
+ require 'goliath'
14
+ require 'em-synchrony'
15
+ require 'goliath/test_helper'
16
+ require 'support/test_helper'
17
+
18
+ # Requires custom matchers & macros, etc from files in ./support/ & subdirs
19
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
20
+
21
+ # Configure rspec
22
+ RSpec.configure do |config|
23
+ config.include Goliath::TestHelper, :example_group => {
24
+ :file_path => /spec/
25
+ }
26
+ end
27
+ end
28
+
29
+ Spork.each_run do
30
+ # This code will be run each time you run your specs.
31
+ end
metadata ADDED
@@ -0,0 +1,218 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: icss
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Philip (flip) Kromer for Infochimps
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-07 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ prerelease: false
22
+ name: yajl-ruby
23
+ type: :runtime
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 59
30
+ segments:
31
+ - 0
32
+ - 8
33
+ - 2
34
+ version: 0.8.2
35
+ requirement: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ prerelease: false
38
+ name: gorillib
39
+ type: :runtime
40
+ version_requirements: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 17
46
+ segments:
47
+ - 0
48
+ - 0
49
+ - 7
50
+ version: 0.0.7
51
+ requirement: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ prerelease: false
54
+ name: rspec
55
+ type: :development
56
+ version_requirements: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 2
64
+ - 3
65
+ - 0
66
+ version: 2.3.0
67
+ requirement: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ prerelease: false
70
+ name: yard
71
+ type: :development
72
+ version_requirements: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ hash: 7
78
+ segments:
79
+ - 0
80
+ - 6
81
+ - 0
82
+ version: 0.6.0
83
+ requirement: *id004
84
+ - !ruby/object:Gem::Dependency
85
+ prerelease: false
86
+ name: bundler
87
+ type: :development
88
+ version_requirements: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ hash: 23
94
+ segments:
95
+ - 1
96
+ - 0
97
+ - 0
98
+ version: 1.0.0
99
+ requirement: *id005
100
+ - !ruby/object:Gem::Dependency
101
+ prerelease: false
102
+ name: jeweler
103
+ type: :development
104
+ version_requirements: &id006 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ hash: 7
110
+ segments:
111
+ - 1
112
+ - 5
113
+ - 2
114
+ version: 1.5.2
115
+ requirement: *id006
116
+ - !ruby/object:Gem::Dependency
117
+ prerelease: false
118
+ name: rcov
119
+ type: :development
120
+ version_requirements: &id007 !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ hash: 3
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ requirement: *id007
130
+ description: "Infochimps Stupid Schema library: an avro-compatible data description standard. ICSS completely describes a collection of data (and associated assets) in a way that is expressive, scalable and sufficient to drive remarkably complex downstream processes."
131
+ email: coders@infochimps.com
132
+ executables: []
133
+
134
+ extensions: []
135
+
136
+ extra_rdoc_files:
137
+ - LICENSE.textile
138
+ - README.textile
139
+ files:
140
+ - .document
141
+ - .rspec
142
+ - .watchr
143
+ - CHANGELOG.textile
144
+ - Gemfile
145
+ - Gemfile.lock
146
+ - LICENSE.textile
147
+ - README.textile
148
+ - Rakefile
149
+ - VERSION
150
+ - examples/BulkData.avpr
151
+ - examples/complicated.icss.yaml
152
+ - examples/interop.avsc
153
+ - examples/mail.avpr
154
+ - examples/namespace.avpr
155
+ - examples/org/apache/avro/ipc/HandshakeRequest.avsc
156
+ - examples/org/apache/avro/ipc/HandshakeResponse.avsc
157
+ - examples/org/apache/avro/ipc/trace/avroTrace.avdl
158
+ - examples/org/apache/avro/ipc/trace/avroTrace.avpr
159
+ - examples/org/apache/avro/mapred/tether/InputProtocol.avpr
160
+ - examples/org/apache/avro/mapred/tether/OutputProtocol.avpr
161
+ - examples/simple.avpr
162
+ - examples/weather.avsc
163
+ - icss.gemspec
164
+ - icss_specification.textile
165
+ - init.rb
166
+ - lib/icss.rb
167
+ - lib/icss/brevity.rb
168
+ - lib/icss/code_asset.rb
169
+ - lib/icss/core_ext.rb
170
+ - lib/icss/data_asset.rb
171
+ - lib/icss/message.rb
172
+ - lib/icss/old.rb
173
+ - lib/icss/protocol.rb
174
+ - lib/icss/protocol_set.rb
175
+ - lib/icss/sample_message_call.rb
176
+ - lib/icss/target.rb
177
+ - lib/icss/type.rb
178
+ - lib/icss/type/factory.rb
179
+ - lib/icss/validations.rb
180
+ - lib/icss/view_helper.rb
181
+ - spec/icss_spec.rb
182
+ - spec/spec_helper.rb
183
+ homepage: http://github.com/mrflip/icss
184
+ licenses:
185
+ - MIT
186
+ post_install_message:
187
+ rdoc_options: []
188
+
189
+ require_paths:
190
+ - lib
191
+ required_ruby_version: !ruby/object:Gem::Requirement
192
+ none: false
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ hash: 3
197
+ segments:
198
+ - 0
199
+ version: "0"
200
+ required_rubygems_version: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ">="
204
+ - !ruby/object:Gem::Version
205
+ hash: 3
206
+ segments:
207
+ - 0
208
+ version: "0"
209
+ requirements: []
210
+
211
+ rubyforge_project:
212
+ rubygems_version: 1.7.2
213
+ signing_key:
214
+ specification_version: 3
215
+ summary: "Infochimps Stupid Schema library: an avro-compatible data description standard. ICSS completely describes a collection of data (and associated assets) in a way that is expressive, scalable and sufficient to drive remarkably complex downstream processes."
216
+ test_files:
217
+ - spec/icss_spec.rb
218
+ - spec/spec_helper.rb