icss 0.1.3 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/.watchr +35 -3
  2. data/CHANGELOG.md +38 -0
  3. data/Gemfile +19 -14
  4. data/README.md +296 -0
  5. data/Rakefile +2 -6
  6. data/TODO.md +13 -0
  7. data/VERSION +1 -1
  8. data/examples/avro_examples/complicated.icss.yaml +14 -13
  9. data/examples/bnc.icss.yaml +70 -0
  10. data/examples/chronic.icss.yaml +3 -3
  11. data/examples/license.icss.yaml +7 -0
  12. data/examples/source1.icss.yaml +4 -0
  13. data/examples/source2.icss.yaml +4 -0
  14. data/examples/test_icss.yaml +67 -0
  15. data/icss.gemspec +103 -43
  16. data/lib/icss.rb +37 -15
  17. data/lib/icss/core_types.rb +19 -0
  18. data/lib/icss/error.rb +4 -0
  19. data/{init.rb → lib/icss/init.rb} +0 -0
  20. data/lib/icss/message.rb +124 -66
  21. data/lib/icss/message/message_sample.rb +144 -0
  22. data/lib/icss/protocol.rb +184 -131
  23. data/lib/icss/protocol/code_asset.rb +18 -0
  24. data/lib/icss/protocol/data_asset.rb +23 -0
  25. data/lib/icss/protocol/license.rb +41 -0
  26. data/lib/icss/protocol/source.rb +37 -0
  27. data/lib/icss/protocol/target.rb +68 -0
  28. data/lib/icss/receiver_model.rb +24 -0
  29. data/lib/icss/receiver_model/active_model_shim.rb +36 -0
  30. data/lib/icss/receiver_model/acts_as_catalog.rb +170 -0
  31. data/lib/icss/receiver_model/acts_as_hash.rb +177 -0
  32. data/lib/icss/receiver_model/acts_as_loadable.rb +47 -0
  33. data/lib/icss/receiver_model/acts_as_tuple.rb +100 -0
  34. data/lib/icss/receiver_model/locale/en.yml +27 -0
  35. data/lib/icss/receiver_model/to_geo_json.rb +19 -0
  36. data/lib/icss/receiver_model/tree_merge.rb +34 -0
  37. data/lib/icss/receiver_model/validations.rb +31 -0
  38. data/lib/icss/serialization.rb +51 -0
  39. data/lib/icss/serialization/zaml.rb +443 -0
  40. data/lib/icss/type.rb +148 -501
  41. data/lib/icss/type/base_type.rb +0 -0
  42. data/lib/icss/type/named_type.rb +184 -0
  43. data/lib/icss/type/record_field.rb +77 -0
  44. data/lib/icss/type/record_model.rb +49 -0
  45. data/lib/icss/type/record_schema.rb +54 -0
  46. data/lib/icss/type/record_type.rb +325 -0
  47. data/lib/icss/type/simple_types.rb +72 -0
  48. data/lib/icss/type/structured_schema.rb +288 -0
  49. data/lib/icss/type/type_factory.rb +144 -0
  50. data/lib/icss/type/union_schema.rb +41 -0
  51. data/lib/icss/view_helper.rb +56 -19
  52. data/notes/named_array.md +32 -0
  53. data/notes/on_include_vs_extend_etc.rb +176 -0
  54. data/notes/technical_details.md +278 -0
  55. data/spec/core_types_spec.rb +119 -0
  56. data/spec/fixtures/zaml_complex_hash.yaml +35 -0
  57. data/spec/icss_spec.rb +86 -23
  58. data/spec/message/message_sample_spec.rb +4 -0
  59. data/spec/message_spec.rb +139 -0
  60. data/spec/protocol/license_spec.rb +67 -0
  61. data/spec/protocol/protocol_catalog_spec.rb +48 -0
  62. data/spec/protocol/protocol_validations_spec.rb +176 -0
  63. data/spec/protocol/source_spec.rb +65 -0
  64. data/spec/protocol_spec.rb +91 -37
  65. data/spec/receiver_model_spec.rb +111 -0
  66. data/spec/serialization/zaml_spec.rb +81 -0
  67. data/spec/serialization/zaml_test.rb +473 -0
  68. data/spec/serialization_spec.rb +63 -0
  69. data/spec/spec_helper.rb +24 -7
  70. data/spec/support/icss_test_helper.rb +67 -0
  71. data/spec/support/load_example_protocols.rb +17 -0
  72. data/spec/type/base_type_spec.rb +0 -0
  73. data/spec/type/named_type_spec.rb +75 -0
  74. data/spec/type/record_field_spec.rb +44 -0
  75. data/spec/type/record_model_spec.rb +206 -0
  76. data/spec/type/record_schema_spec.rb +161 -0
  77. data/spec/type/record_type_spec.rb +155 -0
  78. data/spec/type/simple_types_spec.rb +121 -0
  79. data/spec/type/structured_schema_spec.rb +300 -0
  80. data/spec/type/type_catalog_spec.rb +44 -0
  81. data/spec/type/type_factory_spec.rb +93 -0
  82. data/spec/type/union_schema_spec.rb +0 -0
  83. data/spec/type_spec.rb +63 -0
  84. metadata +205 -144
  85. data/CHANGELOG.textile +0 -9
  86. data/Gemfile.lock +0 -40
  87. data/README.textile +0 -29
  88. data/lib/icss/brevity.rb +0 -136
  89. data/lib/icss/code_asset.rb +0 -16
  90. data/lib/icss/core_ext.rb +0 -9
  91. data/lib/icss/data_asset.rb +0 -22
  92. data/lib/icss/old.rb +0 -96
  93. data/lib/icss/protocol_set.rb +0 -48
  94. data/lib/icss/sample_message_call.rb +0 -142
  95. data/lib/icss/target.rb +0 -72
  96. data/lib/icss/type/factory.rb +0 -196
  97. data/lib/icss/validations.rb +0 -16
  98. data/spec/validations_spec.rb +0 -171
@@ -1,9 +0,0 @@
1
- h3. v0.1.0 June 7 2011
2
-
3
- * New receiver from gorillib
4
-
5
- h3. v0.0.3 May 22 2011
6
-
7
- * used gorillib, got rid of active_support, extlib HOORAY
8
- * moved Receiver to gorillib.
9
- * *breaking change*. Gorillib changed the signature of receive() to be @receive(*constructor_args, hsh)@ (formerly, the hsh was first).
@@ -1,40 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- activemodel (3.0.9)
5
- activesupport (= 3.0.9)
6
- builder (~> 2.1.2)
7
- i18n (~> 0.5.0)
8
- activesupport (3.0.9)
9
- builder (2.1.2)
10
- diff-lcs (1.1.2)
11
- git (1.2.5)
12
- gorillib (0.1.1)
13
- i18n (0.5.0)
14
- jeweler (1.5.2)
15
- bundler (~> 1.0.0)
16
- git (>= 1.2.5)
17
- rake
18
- rake (0.8.7)
19
- rcov (0.9.9)
20
- rspec (2.3.0)
21
- rspec-core (~> 2.3.0)
22
- rspec-expectations (~> 2.3.0)
23
- rspec-mocks (~> 2.3.0)
24
- rspec-core (2.3.1)
25
- rspec-expectations (2.3.0)
26
- diff-lcs (~> 1.1.2)
27
- rspec-mocks (2.3.0)
28
- yard (0.6.8)
29
-
30
- PLATFORMS
31
- ruby
32
-
33
- DEPENDENCIES
34
- activemodel (~> 3.0.9)
35
- bundler (~> 1.0.0)
36
- gorillib (~> 0.1.1)
37
- jeweler (~> 1.5.2)
38
- rcov
39
- rspec (~> 2.3.0)
40
- yard (~> 0.6.0)
@@ -1,29 +0,0 @@
1
- h2. The Infochimps Stupid Schema (ICSS)
2
-
3
- An ICSS file is a *complete*, *expressive* description of a collection of related data and all associated assets.
4
-
5
- Assets may include
6
- * data assets (including their location and schema)
7
- * code for api calls (messages) based on the the described records (including their call signature and schema)
8
- * other referenced schema
9
-
10
- See "icss_specification.textile":icss/blob/master/icss_specification.textile for more.
11
-
12
-
13
- h2. Colophon
14
-
15
- h3. Contributing to icss
16
-
17
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
18
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
19
- * Fork the project
20
- * Start a feature/bugfix branch
21
- * Commit and push until you are happy with your contribution
22
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
23
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
24
-
25
- h3. Copyright
26
-
27
- Copyright (c) 2011 Philip (flip) Kromer for Infochimps. See LICENSE.txt for
28
- further details.
29
-
@@ -1,136 +0,0 @@
1
- #
2
- # Doing
3
- #
4
- # require 'icss/brevity'
5
- #
6
- # makes the #inspect method on Icss::Type's be nice and readable,
7
- # not GIGANTE PIQUANTE OY CABRON
8
- #
9
- #
10
- module Icss
11
-
12
- Protocol.class_eval do
13
- def inspect
14
- ["#<#{self.class.name}",
15
- inspect_hsh.map{|k,v| "#{k}=#{v}" },
16
- ">"
17
- ].join(" ")
18
- end
19
-
20
- def inspect_hsh
21
- {
22
- :name => name,
23
- :namespace => @namespace,
24
- :types => (types||[]).map(&:name).inspect,
25
- :messages => (messages||{}).values.map(&:name).inspect,
26
- :data_assets => (data_assets||[]).map(&:name).inspect,
27
- :doc => "'#{(doc||"")[0..30].gsub(/[\n\t\r]+/,' ')}...'",
28
- }
29
- end
30
- end
31
-
32
- Message.class_eval do
33
- def inspect
34
- ["#<#{self.class.name}",
35
- inspect_hsh.map{|k,v| "#{k}=#{v}" },
36
- ">"
37
- ].join(" ")
38
- end
39
-
40
- private
41
- # stuff a compact cartoon of the fields in there
42
- def inspect_hsh
43
- {
44
- :name => name,
45
- :request => summary_of_request_attr, # (request||[]).map(&:type).map(&:name),
46
- :response => summary_of_response_attr,
47
- :errors => errors.inspect,
48
- :protocol => (protocol.present? ? protocol.protocol : nil),
49
- :doc => "'#{(doc||"")[0..30].gsub(/[\n\t\r]+/,' ')}...'",
50
- }
51
- end
52
- end
53
-
54
- Type.class_eval do
55
- def inspect
56
- ["#<#{self.class.name}",
57
- @type,
58
- inspect_hsh.map{|k,v| "#{k}=#{v}" },
59
- ">",
60
- ].compact.join(" ")
61
- end
62
- private
63
- def inspect_hsh
64
- { :name => name,
65
- :doc => "'#{(doc||"")[0..30].gsub(/[\n\t\r]+/,' ')}...'", }
66
- end
67
- end
68
-
69
- RecordField.class_eval do
70
- def inspect
71
- ["#<#{self.class.name}",
72
- inspect_hsh.map{|k,v| "#{k}=#{v}" },
73
- ">",
74
- ].compact.join(" ")
75
- end
76
- private
77
- def inspect_hsh
78
- { :name => name,
79
- :type => expand_type,
80
- :default => default,
81
- :order => @order,
82
- :doc => "'#{(doc||"")[0..30].gsub(/[\n\t\r]+/,' ')}...'",
83
- }.reject{|k,v| v.nil? }
84
- end
85
- end
86
-
87
- PrimitiveType.class_eval do
88
- def inspect
89
- "#<#{self.class.name} #{name}>"
90
- end
91
- end
92
-
93
- NamedType.class_eval do
94
- private
95
- def inspect_hsh
96
- super.merge( :namespace => @namespace )
97
- end
98
- end
99
-
100
- RecordType.class_eval do
101
- private
102
- def inspect_hsh
103
- super.merge( :fields => (fields||[]).inject({}){|h,f| h[f.name] = ((f.type.present? && f.is_reference?) ? f.type.name : f.type) ; h }.inspect )
104
- end
105
- end
106
-
107
- EnumType.class_eval do
108
- private
109
- def inspect_hsh
110
- super.merge( :symbols => symbols.inspect )
111
- end
112
- end
113
-
114
- FixedType.class_eval do
115
- private
116
- def inspect_hsh
117
- super.merge( :size => size.inspect )
118
- end
119
- end
120
-
121
- ArrayType.class_eval do
122
- private
123
- def inspect_hsh
124
- super.merge( :items => items.inspect )
125
- end
126
- end
127
-
128
- MapType.class_eval do
129
- private
130
- def inspect_hsh
131
- super.merge( :values => values.inspect )
132
- end
133
- end
134
-
135
- end
136
-
@@ -1,16 +0,0 @@
1
- module Icss
2
- class CodeAsset
3
- include Receiver
4
- include Receiver::ActsAsHash
5
-
6
- rcvr_accessor :name, String
7
- rcvr_accessor :location, String
8
-
9
- def to_hash()
10
- { :name => name, :location => location}
11
- end
12
-
13
- def to_json() to_hash.to_json ; end
14
-
15
- end
16
- end
@@ -1,9 +0,0 @@
1
- require 'gorillib/object/blank'
2
- require 'gorillib/string/inflections'
3
- require 'gorillib/string/constantize'
4
- require 'gorillib/array/compact_blank'
5
- require 'gorillib/array/extract_options'
6
- require 'gorillib/hash/compact'
7
- require 'gorillib/hash/keys'
8
- require 'gorillib/hash/tree_merge'
9
- require 'gorillib/metaprogramming/class_attribute'
@@ -1,22 +0,0 @@
1
- module Icss
2
- class DataAsset
3
- include Receiver
4
- include Receiver::ActsAsHash
5
-
6
- rcvr_accessor :name, String
7
- rcvr_accessor :location, String
8
- #overriding ruby's deprecated but still present type attr on objects
9
- attr_accessor :type
10
- rcvr_accessor :type, String
11
- rcvr_accessor :doc, String
12
-
13
- def named? nm
14
- name == nm
15
- end
16
-
17
- def to_hash()
18
- { :name => name, :location => location, :type => type, :doc => doc }
19
- end
20
- def to_json() to_hash.to_json ; end
21
- end
22
- end
@@ -1,96 +0,0 @@
1
- module Icss
2
- Protocol.class_eval do
3
-
4
- #
5
- # Returns the asset hash with the passed in asset_name
6
- #
7
- def asset_for_name nm
8
- warn "asset_for_name obsolete, please rewrite"
9
- data_assets.find{|asset| asset.named?(nm) }
10
- end
11
-
12
- #
13
- # Returns the full type for the passed in asset hash
14
- #
15
- def type_for_asset asset
16
- warn "type_for_asset obsolete, please rewrite"
17
- # types.find{|type| type.name == asset['type']}
18
- raise 'use asset.type_obj'
19
- end
20
-
21
- #
22
- # Given an asset name, returns the the record it points to
23
- #
24
- def type_for_asset_name asset_name
25
- warn "type_for_asset_name obsolete, please rewrite"
26
- asset = asset_for_name(asset_name)
27
- type_for_asset(asset)
28
- end
29
-
30
- #
31
- # Given an asset name, return the name of the type it points to
32
- #
33
- def type_name_for_asset_name asset_name
34
- warn "type_name_for_asset_name obsolete, please rewrite"
35
- asset = asset_for_name(asset_name)
36
- asset['type']
37
- end
38
-
39
- #
40
- # Return the avro record with the given name
41
- #
42
- def type_for_name type_name
43
- warn "type_for_name obsolete, please rewrite"
44
- # types.find{|record| record.name == type_name}
45
- Icss::Type.find(type_name)
46
- end
47
-
48
- #
49
- # Fetch the avro fields for a named data asset
50
- #
51
- def fields_for_asset asset_name
52
- warn "fields_for_asset obsolete, please rewrite"
53
- asset = asset_for_name(asset_name)
54
- asset_type = type_for_asset(asset)
55
- asset_type.fields
56
- end
57
-
58
- #
59
- # Fetch the locations on disk of each data asset. WARNING: Assuming relative paths
60
- #
61
- def location_for_asset asset_name
62
- warn "location_for_asset obsolete, please rewrite"
63
- asset = asset_for_name(asset_name)
64
- File.join(dirname, asset['location'])
65
- end
66
-
67
- #
68
- # Return the index of the named field for the named type. Returns (nil) if field
69
- # does not exist
70
- #
71
- def index_of_fieldname asset_name, field_name
72
- warn "index_of_fieldname obsolete, please rewrite"
73
- type = type_for_asset_name(asset_name)
74
- type.index_of_fieldname(field_name)
75
- end
76
-
77
- AVRO_PIG_MAPPING = {
78
- 'string' => 'chararray',
79
- 'int' => 'int',
80
- 'long' => 'long',
81
- 'float' => 'float',
82
- 'double' => 'double',
83
- 'bytes' => 'bytearray',
84
- 'fixed' => 'bytearray'
85
- }
86
-
87
- #
88
- # Add pig fields to a passed in array of avro fields
89
- #
90
- def augment_with_pig_fields fields
91
- warn "augment_with_pig_fields obsolete, please rewrite"
92
- fields.map{|field| field.body['pig_type'] = AVRO_PIG_MAPPING[field.type]; field }
93
- end
94
- end
95
-
96
- end
@@ -1,48 +0,0 @@
1
- # you must require 'icss/protocol_set' explicitly to use it.
2
-
3
- module Icss
4
- #
5
- # Holds a set of icss protocols, with helper methods to load them from a
6
- # directory tree, to merge in a protocol set yaml file, and so forth
7
- #
8
- class ProtocolSet
9
- attr_accessor :protocols
10
-
11
- def initialize
12
- self.protocols = {}
13
- end
14
-
15
-
16
- def register pr
17
- if protocols[pr.fullname]
18
- protocols[pr.fullname].tree_merge!(pr)
19
- else
20
- protocols[pr.fullname] = pr
21
- end
22
- end
23
-
24
- # load and register the protocols in the given filenames
25
- def load_protocols *icss_filenames
26
- icss_filenames = icss_filenames.flatten.compact
27
- icss_filenames.each do |icss_filename|
28
- register Icss::Protocol.receive_from_file(icss_filename)
29
- end
30
- end
31
-
32
- # load and register the set of protocols in the given yaml file.
33
- # it must be a hash with element 'protocol_set', holding an array of
34
- # protocol hashes.
35
- #
36
- # protocol_set:
37
- # - namespace: "..."
38
- # protocol: "..."
39
- def load_protocol_set protocol_set_filename
40
- protocol_set_hsh = YAML.load(File.open(protocol_set_filename))
41
- protocol_set_hsh['protocol_set'].each do |hsh|
42
- register Icss::Protocol.receive(hsh)
43
- end
44
- end
45
- end
46
- end
47
-
48
-
@@ -1,142 +0,0 @@
1
- module Icss
2
- #
3
- # Holds a sample call for a message and its expected response
4
- #
5
- # You may define the request parameters using an array of parameters
6
- # or with the corresponding URL it would render to.
7
- #
8
- # This file also decorates Icss::Message and Icss::Protocol with helper methods for sample calls.
9
- #
10
- class SampleMessageCall
11
- include Receiver
12
- include Receiver::ActsAsHash
13
- rcvr_accessor :name, String
14
- rcvr_accessor :doc, String
15
- rcvr_accessor :request, Array, :default => []
16
- rcvr_accessor :response, Object # a hash suitable for populating the message's @response@ type
17
- attr_accessor :raw_response # the raw http response from fetching
18
- rcvr_accessor :error, String
19
- rcvr_accessor :url, String
20
- attr_accessor :message
21
-
22
- # The URL implied by the given hostname and the sample request parameters.
23
- #
24
- # @param [String] hostname The hostname or hostname:port to include in the URL
25
- # @param [Hash] extra_query_params A hash of extra params to in
26
- #
27
- # The URI expects string values in the hash used to build the query -- if
28
- # calling #to_s on a field won't do what you want, clobber the value beforehand.
29
- #
30
- def full_url hostname, extra_query_params={}
31
- host, port = hostname.split(':', 2)
32
- u = Addressable::URI.new(:host => host, :port => port, :path => self.path, :scheme => 'http')
33
- u.query_values = query_hash(extra_query_params)
34
- u
35
- end
36
-
37
- def query_hash extra_query_params={}
38
- hsh = (@url.present? ? @url.query_values : request.first.to_hash) rescue {}
39
- hsh = hsh.merge extra_query_params
40
- hsh.each{|k,v| hsh[k] = v.to_s }
41
- hsh
42
- end
43
-
44
- def path
45
- ((@url && @url.path).present? ? @url.path : "/#{message.path}" )
46
- end
47
-
48
- # @param [String, Addressable::URI]
49
- # the URL can be fully-qualified (htttp://api.infochimps.com/this/that?the=other) or relative (this/that?the=other)
50
- # and the path must match that of the message.
51
- #
52
- def url= new_url
53
- if new_url.is_a?(String)
54
- unless new_url.include?('?') then warn "sample request url should have a '?' introducing its query parameters: {#{new_url}}" ; end
55
- new_url = Addressable::URI.parse(new_url)
56
- end
57
- @url = new_url
58
- end
59
-
60
- # Whips up the class implied by the ICSS type of this message's response,
61
- # and populates it using the response hash.
62
- def response_obj
63
- return if response.blank?
64
- klass = message.response.ruby_klass
65
- klass.receive(response.compact_blank!)
66
- end
67
-
68
- # retrieve the response from the given host, storing it in response. this
69
- # catches all server errors and constructs a dummy response hash if the call
70
- # fails.
71
- def fetch_response! hostname="", extra_query_params={}
72
- self.raw_response = fetch_raw_response( full_url(hostname, extra_query_params) )
73
- begin
74
- resp_hsh = JSON.load(raw_response.body)
75
- rescue StandardError => e
76
- warn [" error parsing response: #{e}"].join("\n")
77
- self.response = nil
78
- self.error = "JsonParseError"
79
- return
80
- end
81
- if raw_response.code == 200
82
- self.response = resp_hsh
83
- self.error = nil
84
- else
85
- self.response = nil
86
- self.error = resp_hsh["error"]
87
- end
88
- end
89
-
90
- private
91
-
92
- def fetch_raw_response full_url
93
- RestClient.get(full_url.to_s) do |response, request, result|
94
- response
95
- end
96
- end
97
- end
98
- end
99
-
100
- class Icss::Message
101
- rcvr_accessor :samples, Array, :of => Icss::SampleMessageCall, :default => []
102
- end
103
-
104
- class Icss::Protocol
105
-
106
- #
107
- # a hash for dumping to file:
108
- # @example: from the whole thing, would dump only this:
109
- #
110
- # namespace: util.time
111
- # protocol: chronic
112
- # messages:
113
- # parse:
114
- # samples:
115
- # - url: "?now=5%3A06%3A07%202010-08-08&time_str=Yesterday"
116
- # response: { "time": "2010-08-07 05:06:07 UTC", "epoch_seconds": 1281225967 }
117
- #
118
- def message_samples_hash
119
- hsh = { :namespace => namespace, :protocol => protocol, :messages => {} }
120
- messages.each do |msg_name, msg|
121
- hsh[:messages][msg_name] = { :samples => [] }
122
- msg.samples.each do |sample_req|
123
- sample_hsh = {
124
- :name => sample_req.name,
125
- :doc => sample_req.doc,
126
- }
127
- if sample_req.response.present?
128
- then sample_hsh[:response] = sample_req.response
129
- else sample_hsh[:error] = sample_req.error
130
- end
131
- if sample_req.url.present?
132
- then sample_hsh[:url] = sample_req.url.to_s
133
- else sample_hsh[:request] = sample_req.request
134
- end
135
- sample_hsh.compact_blank!
136
- hsh[:messages][msg_name][:samples] << sample_hsh
137
- end
138
- end
139
- return hsh
140
- end
141
-
142
- end