icss 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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