bliss 0.0.9 → 0.1.0

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.
@@ -1,7 +1,12 @@
1
+ == 0.1.0
2
+ * Added support for (possible) "content_values" on Bliss::Format.
3
+
1
4
  == 0.0.9
2
5
 
3
6
  * Features
4
7
 
8
+ * Added on_timeout callback.
9
+ * Introduced Bliss::Format, which linked to a Bliss::Parser are checked during parsing process. They are defined with a bunch of specs given as YAML.
5
10
  * added support for Gzip (content type is autodetected).
6
11
  * on_max_unhandled_bytes callback block. Which receives the amount of bytes and a block to execute when that limit is reached.
7
12
  * on_tag_close maybe used without a specific tag name, and block now handles "current depth" array.
@@ -3,26 +3,30 @@
3
3
  require 'rubygems'
4
4
  require 'bliss'
5
5
 
6
- path = 'http://www.yourdomain.com/input.xml'
6
+ path = 'http://www.yourdomain.com/input.xml' # it supports tar.gz too!
7
7
 
8
- parser = Bliss::ParserMachine.new(path, 'output.xml')
8
+ parser = Bliss::Parser.new(path, 'output.xml') # outputs read xml
9
9
  count = 0
10
- p.on_root { |root|
11
- puts root
10
+ parser.on_max_unhandled_bytes(20000) {
11
+ puts 'Stopped parsing caused content data for tag was too big!'
12
+ parser.close
12
13
  }
13
- parser.on_tag_open('ad') { |depth|
14
+ parser.on_tag_open('ads/ad') { |depth|
14
15
  puts depth.inspect
15
16
  }
16
- parser.on_tag_close('ad') { |hash|
17
+ parser.on_tag_close('ads/ad') { |hash, depth|
17
18
  count += 1
18
19
  puts hash.inspect
19
20
  if count == 4
20
21
  parser.close
21
22
  end
22
23
  }
24
+
25
+ parser.on_timeout(5) {
26
+ puts 'Timeout!'
27
+ }
23
28
 
24
29
  parser.parse
25
- puts "Root: #{parser.root}"
26
30
 
27
31
  == Contributing to bliss
28
32
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.9
1
+ 0.1.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "bliss"
8
- s.version = "0.0.9"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Fernando Alonso"]
12
- s.date = "2012-06-04"
12
+ s.date = "2012-06-12"
13
13
  s.description = "streamed xml parsing tool"
14
14
  s.email = "krakatoa1987@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -38,7 +38,9 @@ Gem::Specification.new do |s|
38
38
  "lib/bliss/parser_machine.rb",
39
39
  "lib/hash_extension.rb",
40
40
  "spec.yml",
41
+ "spec/constraint_spec.rb",
41
42
  "spec/format_spec.rb",
43
+ "spec/parser_spec.rb",
42
44
  "spec/spec_helper.rb",
43
45
  "test.rb",
44
46
  "test/helper.rb",
@@ -1,30 +1,22 @@
1
1
  module Bliss
2
2
  class Constraint
3
- #attr_reader :field, :type, :state
4
- attr_reader :depth, :setting, :state
5
-
6
- #TYPES = [:exist, :not_blank, :possible_values]
3
+ attr_accessor :depth, :possible_values
4
+ attr_reader :setting, :state
7
5
 
8
6
  def initialize(depth, setting, params={})
9
7
  @depth = depth
10
8
  @setting = setting
9
+ @possible_values = params[:possible_values].collect(&:to_s) if params.has_key?(:possible_values)
11
10
 
12
11
  @state = :not_checked
13
12
  end
14
13
 
15
- #def initialize(field, type, possible_values=nil)
16
- # if field.is_a? Array
17
- # @field = field
18
- # else
19
- # @field = [field]
20
- # end
21
- # @type = type
22
- # @possible_values = possible_values
23
- #
24
- # @state = :not_checked
25
- #end
14
+ def tag_names
15
+ @depth.split('/').last.gsub('(', '').gsub(')', '').split('|')
16
+ end
26
17
 
27
- def run!(hash)
18
+ # TODO should exist another method passed! for tag_name_required ?
19
+ def run!(hash=nil)
28
20
  @state = :not_checked
29
21
  #@field.each do |field|
30
22
  #if @state == :passed
@@ -32,38 +24,81 @@ module Bliss
32
24
  #end
33
25
  case @setting
34
26
  when :tag_name_required
35
- if !hash.keys.include?(depth.last)
36
- @state = :not_passed
27
+ content = nil
28
+ if hash
29
+ #puts "#{@depth.inspect} - required: #{required.inspect}"
30
+
31
+ found = false
32
+ self.tag_names.each do |key|
33
+ if hash.keys.include?(key)
34
+ found = true
35
+ break
36
+ end
37
+ end
38
+ if found
39
+ @state = :passed
40
+ else
41
+ @state = :not_passed
42
+ end
37
43
  else
38
44
  @state = :passed
39
45
  end
46
+ when :content_values
47
+ if hash
48
+ found = false
49
+ self.tag_names.each do |key|
50
+ content = hash[key]
51
+ puts content
52
+ puts @possible_values.inspect
53
+ if @possible_values.include?(content)
54
+ found = true
55
+ break
56
+ end
57
+ end
58
+ if found
59
+ @state = :passed
60
+ else
61
+ @state = :not_passed
62
+ end
63
+ end
40
64
  #when :not_blank
41
65
  # if hash.has_key?(field) and !hash[field].to_s.empty?
42
66
  # @state = :passed
43
67
  # else
44
68
  # @state = :not_passed
45
69
  # end
46
- #when :possible_values
47
- # if hash.has_key?(field) and @possible_values.include?(hash[field])
48
- # @state = :passed
49
- # else
50
- # @state = :not_passed
51
- # end
52
70
  end
53
71
  #end
54
72
  @state
55
73
  end
56
74
 
75
+ def ended!
76
+ case @setting
77
+ when :tag_name_required
78
+ if @state == :not_checked
79
+ @state = :not_passed
80
+ end
81
+ end
82
+ end
83
+
57
84
  def detail
58
- if @state == :not_passed
59
- detail = case @type
60
- when :tag_name_required
61
- [@field.join(" or "), "missing"]
62
- #when :not_blank
63
- # [@field.join(" or "), "blank"]
64
- #when :possible_values
65
- # [@field.join(" or "), "invalid"]
66
- end
85
+ self.ended! # TODO esto es una chota de codigo groncho!
86
+
87
+ case @state
88
+ when :not_passed
89
+ case @setting
90
+ when :tag_name_required
91
+ [@depth, "missing"]
92
+ #when :not_blank
93
+ # [@field.join(" or "), "blank"]
94
+ #when :possible_values
95
+ # [@field.join(" or "), "invalid"]
96
+ end
97
+ when :passed
98
+ case @setting
99
+ when :tag_name_required
100
+ [@depth, "exists"]
101
+ end
67
102
  end
68
103
  end
69
104
 
@@ -4,9 +4,8 @@ module Bliss
4
4
  class Format
5
5
  @@keywords = %w{ tag_name_required content_required tag_name_type content_type tag_name_format content_format tag_name_values content_values }
6
6
 
7
- def initialize
8
- yml = YAML.load_file('/home/fernando/desarrollo/workspace/experimentos/bliss/spec.yml')
9
- self.specifications = yml
7
+ def initialize(filepath)
8
+ self.specifications = YAML.load_file(filepath)
10
9
  end
11
10
 
12
11
  # TODO for debugging only!
@@ -21,77 +20,106 @@ module Bliss
21
20
 
22
21
  def constraints
23
22
  return [] if not (@specs.is_a? Hash and @specs.size > 0)
23
+ return @constraints if @constraints
24
24
 
25
- constraints = []
25
+ @constraints = []
26
26
 
27
27
  @specs.recurse(true) do |depth, value|
28
- if !@@keywords.include?(depth.last)
29
- settings = @specs.value_at_chain(depth).select{|key| @@keywords.include?(key) }
28
+ if value.is_a? Hash and !@@keywords.include?(depth.last)
29
+ settings = value.select { |key| @@keywords.include?(key) }
30
30
  end
31
- if settings
31
+ #settings = @specs.value_at_chain(depth).select{|key| @@keywords.include?(key) }
32
+ if settings.is_a? Hash and !@@keywords.include?(depth.last)
32
33
  settings.merge!({"tag_name_required" => true}) if not settings.has_key?("tag_name_required")
33
34
 
34
- puts settings.inspect
35
+ # TODO this is an ugly way to move tag_name_values to the end!
36
+ settings.store('tag_name_values', settings.delete('tag_name_values')) if settings.has_key?('tag_name_values')
37
+ settings.store('content_values', settings.delete('content_values')) if settings.has_key?('content_values')
35
38
 
36
- # tag_name_required constraint:
39
+ #puts settings.inspect
37
40
 
38
- settings.each_pair { |setting, value|
39
- case setting
40
- when "tag_name_required"
41
- if value == true
42
- constraints.push(Bliss::Constraint.new(depth, :tag_name_required))
43
- end
44
- end
45
- }
46
-
47
- #required_fields.each do |field|
48
- # constraints.concat(Sumavisos::Parsers::Constraint.build_constraint(field, [:exist, :not_blank]).dup)
49
- #end
41
+ #depth_name = nil
42
+ #setting_to_constraints(depth, settings).each { |cc|
43
+ #cc.depth = depth_name
44
+ # @constraints.push(cc) #Bliss::Constraint.new(depth_name, cc.setting))
45
+ #}
46
+ @constraints.concat(Bliss::Format.settings_to_constraints(depth, settings))
50
47
 
51
- ###
52
-
53
- #puts "#{depth.join('/')}: #{settings.inspect}"
54
48
  end
55
49
  end
56
50
 
57
- puts constraints.inspect
58
-
59
- return constraints
51
+ return @constraints
60
52
  end
61
-
62
- # during parsing
63
- # Sumavisos::Parsers::Validator.check_constraints(ad, constraints.select{|c| [:not_checked, :passed].include?(c.state)})
64
-
65
- # @constraints.select{|c| c.state == :not_passed }.collect(&:detail)
66
-
67
- def ad_constraints(root, vertical)
68
- #required_fields = Sumavisos::Parsers::Validator::FIELDS['all']['required'].dup
69
- #required_fields.concat(Sumavisos::Parsers::Validator::FIELDS[vertical]['required'])
70
-
71
- #constraints = []
72
- #required_fields.each do |field|
73
- # constraints.concat(Sumavisos::Parsers::Constraint.build_constraint(field, [:exist, :not_blank]).dup)
74
- #end
75
-
76
- if vertical == 'property'
77
- constraints.concat(Sumavisos::Parsers::Constraint.build_constraint(['type'], [:possible_values], Sumavisos::Parsers::Validator::VALID_PROPERTY_TYPES).dup)
78
- end
79
53
 
80
- constraints
54
+ def self.settings_to_constraints(depth, settings)
55
+ # TODO perhaps the Constraint model should handle this
56
+ # e.g., constraint.add_depth (as array)
57
+ # then internally it creates xpath-like depth
58
+
59
+ current_constraints = []
60
+ depth_name = nil
61
+ content_values = nil
62
+ #puts "#{depth.join('/')}: #{settings.inspect}"
63
+ settings.each_pair { |setting, value|
64
+ case setting
65
+ when "tag_name_required"
66
+ if value == true
67
+ depth_name ||= depth.join('/')
68
+ current_constraints.push(Bliss::Constraint.new(depth_name, :tag_name_required))
69
+ end
70
+ when "tag_name_values"
71
+ depth_name = depth[0..-2].join('/')
72
+ depth_name << "/" if depth_name.size > 0
73
+ depth_name << "(#{value.join('|')})" # TODO esto funciona solo en el ultimo step del depth :/
74
+ when "content_values"
75
+ current_constraints.push(Bliss::Constraint.new(depth_name, :content_values, {:possible_values => value}))
76
+ end
77
+ }
78
+ current_constraints.each {|cc|
79
+ cc.depth = depth_name
80
+ }
81
+ current_constraints
81
82
  end
82
83
 
83
- def check_constraints(ads, constraints)
84
- errors = []
85
-
86
- ads = [ads] if not ads.is_a? Array
87
-
88
- ads.each do |ad|
89
- constraints.each do |constraint|
90
- constraint.run!(ad)
91
- end
84
+ #def open_tag_constraints(depth)
85
+ # # raise error if not depth.is_a? Array
86
+ # begin
87
+ # to_check_constraints = self.to_check_constraints.select {|c| [:tag_name_required].include?(c.setting) }.select {|c| Regexp.new(c.depth).match(depth) }
88
+ # rescue
89
+ # []
90
+ # end
91
+ #end
92
+
93
+ #def close_tag_constraints(depth)
94
+ # # raise error if not depth.is_a? Array
95
+ # begin
96
+ # to_check_constraints = self.to_check_constraints.select {|c| Regexp.new(c.depth.split('/')[0..-2].join('/')).match(depth) }
97
+ # rescue
98
+ # []
99
+ # end
100
+ #end
101
+
102
+ # constraint set model? constraints.valid.with_depth(['root', 'ads']) ???
103
+ def to_check_constraints
104
+ # raise error if not depth.is_a? Array
105
+ begin
106
+ to_check_constraints = constraints.select {|c| [:not_checked, :passed].include?(c.state) }
107
+ to_check_constraints
108
+ rescue
109
+ []
92
110
  end
111
+ end
93
112
 
94
- return errors
113
+ def details
114
+ @constraints.collect(&:detail)
95
115
  end
116
+
117
+ def error_details
118
+ @constraints.select {|c| c.state == :not_passed }.collect(&:detail)
119
+ end
120
+
121
+ # reset_constraints_state
122
+ # build_constraints
123
+
96
124
  end
97
125
  end
@@ -14,10 +14,26 @@ module Bliss
14
14
 
15
15
  @root = nil
16
16
  @nodes = nil
17
+ @formats = []
17
18
 
18
19
  on_root {}
19
20
  end
20
21
 
22
+ def add_format(format)
23
+ @formats.push(format)
24
+ end
25
+
26
+ def load_constraints_on_parser_machine
27
+ @parser_machine.constraints(@formats.collect(&:constraints).flatten)
28
+ end
29
+
30
+ def formats_details
31
+ @formats.each do |format|
32
+ puts format.details.inspect
33
+ end
34
+ end
35
+
36
+ # deprecate this, use depth at on_tag_open or on_tag_close instead
21
37
  def on_root(&block)
22
38
  return false if not block.is_a? Proc
23
39
  @parser_machine.on_root { |root|
@@ -26,23 +42,23 @@ module Bliss
26
42
  }
27
43
  end
28
44
 
29
- def on_tag_open(element='default', &block)
45
+ def on_tag_open(element='.', &block)
30
46
  return false if block.arity != 1
31
47
 
32
48
  overriden_block = Proc.new { |depth|
33
49
  if not element == 'default'
34
50
  reset_unhandled_bytes
35
51
  end
52
+
36
53
  block.call(depth)
37
54
  }
38
55
  @parser_machine.on_tag_open(element, overriden_block)
39
56
  end
40
57
 
41
- def on_tag_close(element='default', &block)
58
+ def on_tag_close(element='.', &block)
42
59
  overriden_block = Proc.new { |hash, depth|
43
- #if not element == 'default'
44
- reset_unhandled_bytes
45
- #end
60
+ reset_unhandled_bytes
61
+
46
62
  block.call(hash, depth)
47
63
  }
48
64
  @parser_machine.on_tag_close(element, overriden_block)
@@ -53,6 +69,11 @@ module Bliss
53
69
  @on_max_unhandled_bytes = block
54
70
  end
55
71
 
72
+ def on_timeout(seconds, &block)
73
+ @timeout = seconds
74
+ @on_timeout = block
75
+ end
76
+
56
77
  def wait_tag_close(element)
57
78
  @wait_tag_close = "</#{element}>"
58
79
  end
@@ -68,7 +89,6 @@ module Bliss
68
89
  @on_max_unhandled_bytes.call
69
90
  @on_max_unhandled_bytes = nil
70
91
  end
71
- #self.close
72
92
  end
73
93
  end
74
94
 
@@ -93,9 +113,15 @@ module Bliss
93
113
 
94
114
  def parse
95
115
  reset_unhandled_bytes if check_unhandled_bytes?
116
+ load_constraints_on_parser_machine
96
117
 
97
118
  EM.run do
98
- http = EM::HttpRequest.new(@path).get
119
+ http = nil
120
+ if @timeout
121
+ http = EM::HttpRequest.new(@path, :connect_timeout => @timeout, :inactivity_timeout => @timeout).get
122
+ else
123
+ http = EM::HttpRequest.new(@path).get
124
+ end
99
125
 
100
126
  @autodetect_compression = true
101
127
  compression = :none
@@ -154,6 +180,9 @@ module Bliss
154
180
  }
155
181
  http.errback {
156
182
  #puts 'errback'
183
+ if @timeout
184
+ @on_timeout.call
185
+ end
157
186
  secure_close
158
187
  }
159
188
  http.callback {
@@ -167,12 +196,6 @@ module Bliss
167
196
  file_close
168
197
  end
169
198
 
170
- def autodetect_compression(http)
171
- #compression = :none
172
- puts compression
173
- return compression
174
- end
175
-
176
199
  def handle_wait_tag_close(chunk)
177
200
  begin
178
201
  last_index = chunk.index(@wait_tag_close)
@@ -209,9 +232,3 @@ module Bliss
209
232
 
210
233
  end
211
234
  end
212
-
213
- #require 'stringio'
214
- #str = StringIO.new
215
- #z = Zlib::GzipWriter.new(str)
216
- #z.write(txt)
217
- #z.close
@@ -13,20 +13,28 @@ module Bliss
13
13
  @on_tag_open = {}
14
14
  @on_tag_close = {}
15
15
 
16
+ @constraints = []
17
+
16
18
  @closed = false
17
19
 
18
20
  end
19
21
 
22
+ def constraints(constraints)
23
+ @constraints = constraints
24
+ end
25
+
20
26
  def on_root(&block)
21
27
  @on_root = block
22
28
  end
23
29
 
24
30
  def on_tag_open(element, block)
25
- @on_tag_open.merge!({element => block})
31
+ @on_tag_open.merge!({Regexp.new("#{element}$") => block})
26
32
  end
27
33
 
28
34
  def on_tag_close(element, block)
29
- @on_tag_close.merge!({element => block})
35
+ # TODO
36
+ # check how do we want to handle on_tag_close depths (xpath, array, another)
37
+ @on_tag_close.merge!({Regexp.new("#{element}$") => block})
30
38
  end
31
39
 
32
40
  def close
@@ -50,10 +58,19 @@ module Bliss
50
58
 
51
59
  @depth.push(element) if @depth.last != element
52
60
 
53
- if @on_tag_open.has_key? element
54
- @on_tag_open[element].call(@depth)
55
- elsif @on_tag_open.has_key? 'default'
56
- @on_tag_open['default'].call(@depth)
61
+ # TODO search on hash with xpath style
62
+ # for example:
63
+ # keys: */ad/url
64
+ # keys: root/ad/url
65
+ # @on_tag_close.keys.select {|key| @depth.match(key)}
66
+
67
+ # other example:
68
+ # keys: root/(ad|AD)/description
69
+ ##
70
+
71
+ search_key = @depth.join('/') # element
72
+ @on_tag_open.keys.select{ |r| search_key.match(r) }.each do |reg|
73
+ @on_tag_open[reg].call(@depth)
57
74
  end
58
75
 
59
76
  current = @nodes.pair_at_chain(@depth)
@@ -81,6 +98,22 @@ module Bliss
81
98
  @current_content = ''
82
99
  end
83
100
 
101
+ =begin
102
+ def open_tag_regexps
103
+ return @open_tag_regexps if @open_tag_regexps
104
+
105
+ @open_tag_regexps = @on_tag_open.keys.collect {|key| Regexp.new(key) }
106
+ @open_tag_regexps
107
+ end
108
+
109
+ def close_tag_regexps
110
+ return @close_tag_regexps if @close_tag_regexps
111
+
112
+ @close_tag_regexps = @on_tag_close.keys.collect {|key| Regexp.new(key) }
113
+ @close_tag_regexps
114
+ end
115
+ =end
116
+
84
117
  def characters(string)
85
118
  return if is_closed?
86
119
  concat_content(string)
@@ -107,11 +140,37 @@ module Bliss
107
140
  end
108
141
  end
109
142
  @current_content = ''
143
+
144
+ # TODO search on hash with xpath style
145
+ # for example:
146
+ # keys: */ad/url
147
+ # keys: root/ad/url
148
+ # @on_tag_close.keys.select {|key| @depth.match(key)}
149
+ ##
150
+
151
+ search_key = @depth.join('/') # element
110
152
 
111
- if @on_tag_close.has_key? element
112
- @on_tag_close[element].call(value_at, @depth)
113
- elsif @on_tag_close.has_key? 'default'
114
- @on_tag_close['default'].call(value_at, @depth)
153
+ if @depth.last == 'ad'
154
+ #puts search_key
155
+ #puts value_at.keys.inspect
156
+ #ad array #puts @constraints.select{|c| search_key.match(Regexp.new("#{c.depth.split('/').join('/')}$"))}.inspect
157
+ #puts current.keys.inspect
158
+ # others puts @constraints.select{|c| search_key.match(Regexp.new("#{c.depth.split('/')[0..-2].join('/')}$"))}.inspect
159
+ end
160
+
161
+ @on_tag_close.keys.select{ |r| search_key.match(r) }.each do |reg|
162
+ @on_tag_close[reg].call(value_at, @depth)
163
+ end
164
+ # TODO constraint should return Regexp like depth too
165
+
166
+ #puts @constraints.collect(&:state).inspect
167
+
168
+ @constraints.select{|c| [:not_checked, :passed].include?(c.state) }.select {|c| search_key.match(Regexp.new("#{c.depth.split('/').join('/')}$")) }.each do |constraint|
169
+ #puts "search_key: #{search_key}"
170
+ #puts "value_at.inspect: #{value_at.inspect}"
171
+ #puts "current.inspect: #{current.inspect}"
172
+
173
+ constraint.run!(current)
115
174
  end
116
175
 
117
176
  @depth.pop if @depth.last == element
@@ -125,7 +184,7 @@ module Bliss
125
184
  end
126
185
 
127
186
  def end_document
128
- puts @nodes.inspect
187
+ #puts @nodes.inspect
129
188
  end
130
189
  end
131
190
  end
data/spec.yml CHANGED
@@ -1,23 +1,27 @@
1
1
  # TODO content_type = url
2
2
  ---
3
- root:
3
+ trovit:
4
+ tag_name_values: [ root, trovit, sumavisos ]
5
+ ad: &ad
6
+ id:
7
+ content_type: numeric
8
+ description:
9
+ tag_name_values: [ description, content ]
10
+ content_type: string
11
+ pictures:
12
+ tag_name_required: false
13
+ picture:
14
+ tag_name_required: false
15
+ picture_url:
16
+ tag_name_required: true
17
+ tag_name_values: [ url, picture_url ]
18
+ content_type: string
19
+ content_format: /http:\/\/\w+/
20
+ url:
21
+ content_format: /http:\/\/\w+/
22
+ date:
23
+ content_type: date
4
24
  ads:
5
- tag_name_values: [ ads, jobs, job ]
25
+ tag_name_required: false
6
26
  ad:
7
- id:
8
- content_type: numeric
9
- description:
10
- tag_name_values: [ description, content ]
11
- content_type: string
12
- pictures:
13
- tag_name_required: false
14
- picture:
15
- tag_name_required: false
16
- url:
17
- tag_name_required: true
18
- content_type: string
19
- content_format: /http:\/\/\w+/
20
- url:
21
- content_format: /http:\/\/\w+/
22
- date:
23
- content_type: date
27
+ <<: *ad
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bliss::Constraint do
4
+ describe 'run!' do
5
+ it 'should pass' do
6
+ constraint = Bliss::Constraint.new("root", :tag_name_required)
7
+ constraint.run!({'root' => {'tag_1' => 'test', 'tag_2' => 'test'}})
8
+ constraint.state.should == :passed
9
+ end
10
+
11
+ it 'should pass too' do
12
+ constraint = Bliss::Constraint.new("(root|ROOT)", :tag_name_required)
13
+ constraint.run!({'ROOT' => {'tag_1' => 'test', 'tag_2' => 'test'}})
14
+ constraint.state.should == :passed
15
+ end
16
+
17
+ it 'should not pass' do
18
+ constraint = Bliss::Constraint.new("(root|ROOT)", :tag_name_required)
19
+ constraint.run!({'another' => {'tag_1' => 'test', 'tag_2' => 'test'}})
20
+ constraint.state.should == :not_passed
21
+ end
22
+ end
23
+ end
@@ -4,60 +4,34 @@ require 'spec_helper'
4
4
 
5
5
  describe Bliss::Format do
6
6
  before do
7
- #@openx_banner = mock(OpenX::Services::Banner)
8
7
  @format = Bliss::Format.new
9
8
  end
10
9
 
11
10
  describe '.constraints' do
12
- #before do
13
- #end
14
-
15
11
  it 'should do it' do
16
- @format.constraints.size.should == 8
12
+ @format.constraints.should be_a(Array)
13
+ #@format.constraints.size.should == 8
17
14
  end
18
15
  end
19
16
 
20
- #describe '.traffic' do
21
- # before do
22
- # @openx_banner.stub(:statistics) { YAML.load_file('spec/fixtures/openx_banner_statistics.yml') }
23
- # OpenX::Services::Banner.should_receive(:find).with(1).and_return(@openx_banner)
24
- # @banner = Banner.new(1)
25
- # end
26
-
27
- # it 'should return statistics' do
28
- # @banner.traffic(Date.today, Date.today).should be_kind_of(Hash)
29
- # end
30
- #end
31
-
32
- # describe '.created' do
33
- # context 'when last creation is less than 2 days ago' do
34
- # before do
35
- # @site.stub(:last_creation_day_in_week) { Date.today - 1 }
36
- # end
37
-
38
- # it 'should be ok' do
39
- # @site_evaluation.created[@site.id]['created'][0].should == 'ok'
40
- # end
41
- # end
42
-
43
- # context 'when last creation is between 2 and 7 days ago' do
44
- # before do
45
- # @site.stub(:last_creation_day_in_week) { Date.today - 3 }
46
- # end
47
-
48
- # it 'should be a warning' do
49
- # @site_evaluation.created[@site.id]['created'][0].should == 'warning'
50
- # end
51
- # end
17
+ describe '#settings_to_constraints' do
18
+ it 'should return an array with a Bliss::Constraint object' do
19
+ constraints = Bliss::Format.settings_to_constraints(['root'], {'tag_name_required' => true})
20
+ constraints.should be_a(Array)
21
+ constraints.size.should == 1
22
+ constraints.first.should be_a(Bliss::Constraint)
23
+ end
52
24
 
53
- # context 'when last creation is more than 7 days ago' do
54
- # before do
55
- # @site.stub(:last_creation_day_in_week) { Date.today - 8 }
56
- # end
25
+ it 'should have depth and setting loaded' do
26
+ constraints = Bliss::Format.settings_to_constraints(['root'], {'tag_name_required' => true})
27
+ constraints.first.depth.should == 'root'
28
+ constraints.first.setting.should == :tag_name_required
29
+ end
57
30
 
58
- # it 'should be an alert' do
59
- # @site_evaluation.created[@site.id]['created'][0].should == 'alert'
60
- # end
61
- # end
62
- # end
31
+ it 'should have multiple depths' do
32
+ constraints = Bliss::Format.settings_to_constraints(['root'], {'tag_name_required' => true, 'tag_name_values' => ['root', 'ROOT']})
33
+ constraints.first.depth.should == '(root|ROOT)'
34
+ constraints.first.setting.should == :tag_name_required
35
+ end
36
+ end
63
37
  end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ #require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+ #require_dependency 'xmlrpc/client'
4
+
5
+ describe Bliss::Parser do
6
+ before do
7
+ @parser = Bliss::Parser.new('http://www.topdiffusion.com/flux/topdiffusion_adsdeck.xml')
8
+ @format = Bliss::Format.new
9
+ @parser.add_format(@format)
10
+ end
11
+
12
+ context 'when parsing a valid document' do
13
+ before do
14
+ begin
15
+ @parser.parse
16
+ rescue
17
+ end
18
+ end
19
+
20
+ describe '.formats_details' do
21
+ it 'should have all required keys as existing' do
22
+ puts @parser.formats_details.inspect
23
+ end
24
+ end
25
+ end
26
+ end
data/test.rb CHANGED
@@ -3,14 +3,17 @@ require 'bliss'
3
3
 
4
4
  p = Bliss::Parser.new('', 'output.xml')
5
5
  p.wait_tag_close('ad')
6
- #p.on_max_unhandled_bytes(20000) {
7
- # puts 'Reached Max Unhandled Bytes'
8
- # p.close
9
- #}
6
+ p.on_max_unhandled_bytes(20000) {
7
+ puts 'Unhandled bytes!'
8
+ }
10
9
 
11
10
  @count = 0
12
11
  @makes = 0
13
12
 
13
+ f = Bliss::Format.new
14
+
15
+ p.add_format(f)
16
+
14
17
  p.on_tag_close('ad') { |hash, depth|
15
18
  if hash.has_key?('make')
16
19
  @makes += 1
@@ -45,3 +48,5 @@ end
45
48
 
46
49
  puts @count
47
50
  puts @makes
51
+
52
+ puts p.formats_details.inspect
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bliss
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-04 00:00:00.000000000 Z
12
+ date: 2012-06-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
16
- requirement: &16900020 !ruby/object:Gem::Requirement
16
+ requirement: &8121280 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.5.2
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *16900020
24
+ version_requirements: *8121280
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: eventmachine
27
- requirement: &16899520 !ruby/object:Gem::Requirement
27
+ requirement: &8120500 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0.beta.4
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *16899520
35
+ version_requirements: *8120500
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: em-http-request
38
- requirement: &16898800 !ruby/object:Gem::Requirement
38
+ requirement: &8119480 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.0.2
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *16898800
46
+ version_requirements: *8119480
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
- requirement: &16898260 !ruby/object:Gem::Requirement
49
+ requirement: &8118780 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 2.8.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *16898260
57
+ version_requirements: *8118780
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: bundler
60
- requirement: &16897260 !ruby/object:Gem::Requirement
60
+ requirement: &8117900 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 1.1.3
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *16897260
68
+ version_requirements: *8117900
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: jeweler
71
- requirement: &16895760 !ruby/object:Gem::Requirement
71
+ requirement: &8132400 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 1.6.4
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *16895760
79
+ version_requirements: *8132400
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: simplecov
82
- requirement: &16911540 !ruby/object:Gem::Requirement
82
+ requirement: &8131260 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *16911540
90
+ version_requirements: *8131260
91
91
  description: streamed xml parsing tool
92
92
  email: krakatoa1987@gmail.com
93
93
  executables: []
@@ -117,7 +117,9 @@ files:
117
117
  - lib/bliss/parser_machine.rb
118
118
  - lib/hash_extension.rb
119
119
  - spec.yml
120
+ - spec/constraint_spec.rb
120
121
  - spec/format_spec.rb
122
+ - spec/parser_spec.rb
121
123
  - spec/spec_helper.rb
122
124
  - test.rb
123
125
  - test/helper.rb
@@ -137,7 +139,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
139
  version: '0'
138
140
  segments:
139
141
  - 0
140
- hash: 3727479071019105598
142
+ hash: -4543548141741406741
141
143
  required_rubygems_version: !ruby/object:Gem::Requirement
142
144
  none: false
143
145
  requirements: