utilrb 1.3.3 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,20 @@
1
+ === Version 1.4.0
2
+
3
+ * release the latest git version. utilrb has not seen any release for a very
4
+ long time, and did not move so much anyway. The reason for this release is
5
+ mainly to fix rubygem installation between older rubygem version and newest
6
+ ruby version
7
+
8
+ === Version 1.3.4
9
+
10
+ * fixes a minor problem with PkgConfig handling on broken installations.
11
+ pkg-config is picky about all dependencies being installed on the system.
12
+ The issue is that pkg-config --list-all will stop in the middle of the
13
+ enumeration if one of the packages misses some dependencies.
14
+ PkgConfig.has_package? was using --list-all through PkgConfig.each_package,
15
+ and therefore was wrongly returning false sometimes.
16
+ Moved it to pkg-config --exists, which works.
17
+
1
18
  === Version 1.3.3
2
19
 
3
20
  * fixed a problem with WeakRef crashing on 1.8.7p172. This version of weakref
data/Manifest.txt CHANGED
@@ -17,6 +17,8 @@ lib/utilrb/array.rb
17
17
  lib/utilrb/array/to_s.rb
18
18
  lib/utilrb/column_formatter.rb
19
19
  lib/utilrb/common.rb
20
+ lib/utilrb/configsearch.rb
21
+ lib/utilrb/configsearch/configuration_finder.rb
20
22
  lib/utilrb/dir.rb
21
23
  lib/utilrb/dir/empty.rb
22
24
  lib/utilrb/enumerable.rb
@@ -30,23 +32,29 @@ lib/utilrb/exception/full_message.rb
30
32
  lib/utilrb/gc.rb
31
33
  lib/utilrb/gc/force.rb
32
34
  lib/utilrb/hash.rb
35
+ lib/utilrb/hash/recursive_merge.rb
33
36
  lib/utilrb/hash/slice.rb
34
37
  lib/utilrb/hash/to_s.rb
35
38
  lib/utilrb/hash/to_sym_keys.rb
36
39
  lib/utilrb/kernel.rb
37
40
  lib/utilrb/kernel/arity.rb
41
+ lib/utilrb/kernel/load_dsl_file.rb
38
42
  lib/utilrb/kernel/options.rb
39
43
  lib/utilrb/kernel/poll.rb
40
44
  lib/utilrb/kernel/require.rb
41
45
  lib/utilrb/kernel/swap.rb
46
+ lib/utilrb/kernel/with_module.rb
42
47
  lib/utilrb/logger.rb
43
48
  lib/utilrb/logger/forward.rb
44
49
  lib/utilrb/logger/hierarchy.rb
50
+ lib/utilrb/logger/io.rb
51
+ lib/utilrb/marshal/load_with_missing_constants.rb
45
52
  lib/utilrb/module.rb
46
53
  lib/utilrb/module/ancestor_p.rb
47
54
  lib/utilrb/module/attr_enumerable.rb
48
55
  lib/utilrb/module/attr_predicate.rb
49
56
  lib/utilrb/module/cached_enum.rb
57
+ lib/utilrb/module/const_defined_here_p.rb
50
58
  lib/utilrb/module/define_method.rb
51
59
  lib/utilrb/module/define_or_reuse.rb
52
60
  lib/utilrb/module/include.rb
@@ -54,6 +62,7 @@ lib/utilrb/module/inherited_enumerable.rb
54
62
  lib/utilrb/object.rb
55
63
  lib/utilrb/object/address.rb
56
64
  lib/utilrb/object/attribute.rb
65
+ lib/utilrb/object/scoped_eval.rb
57
66
  lib/utilrb/object/singleton_class.rb
58
67
  lib/utilrb/objectstats.rb
59
68
  lib/utilrb/pkgconfig.rb
@@ -61,6 +70,7 @@ lib/utilrb/set.rb
61
70
  lib/utilrb/set/to_s.rb
62
71
  lib/utilrb/socket/tcp_server.rb
63
72
  lib/utilrb/socket/tcp_socket.rb
73
+ lib/utilrb/symbol/to_str.rb
64
74
  lib/utilrb/time.rb
65
75
  lib/utilrb/time/to_hms.rb
66
76
  lib/utilrb/unbound_method.rb
@@ -69,6 +79,7 @@ lib/utilrb/value_set.rb
69
79
  lib/utilrb/weakref.rb
70
80
  patches/gc_live_objects.patch
71
81
  test/data/test_pkgconfig.pc
82
+ test/data/test_pkgconfig_empty.pc
72
83
  test/test_array.rb
73
84
  test/test_config.rb
74
85
  test/test_dir.rb
data/README.txt CHANGED
@@ -1,7 +1,9 @@
1
- Utilrb
2
- http://utilrb.rubyforge.org
3
- http://www.rubyforge.org/projects/utilrb
4
- http://github.com/doudou/util-rb (git repository)
1
+ = Utilrb
2
+ http://utilrb.rubyforge.org
3
+ http://www.rubyforge.org/projects/utilrb
4
+ http://github.com/doudou/util-rb (git repository)
5
+
6
+ == License
5
7
 
6
8
  Copyright (c) 2006-2008
7
9
  Sylvain Joyeux <sylvain.joyeux@m4x.org>
@@ -10,10 +12,12 @@ Copyright (c) 2006-2008
10
12
  This work is licensed under the BSD license. See License.txt for details
11
13
 
12
14
  == What is Utilrb ?
15
+
13
16
  Utilrb is yet another Ruby toolkit, in the spirit of facets. It includes all
14
- the standard class extensions I use in my own projects like Genom.rb.
17
+ the standard class extensions I use in other projects.
15
18
 
16
19
  == Installation
20
+
17
21
  The only dependency Utilrb has is flexmock if you want to run tests. It is
18
22
  available as a gem, so you can run
19
23
 
data/Rakefile CHANGED
@@ -1,49 +1,53 @@
1
1
  require 'rake'
2
- require 'rake/rdoctask'
3
-
4
- # FIX: Hoe always calls rdoc with -d, and diagram generation fails here
5
- class Rake::RDocTask
6
- alias __option_list__ option_list
7
- def option_list
8
- options = __option_list__
9
- options.delete("-d")
10
- options
11
- end
12
- end
13
-
14
2
  require './lib/utilrb/common'
15
3
 
16
4
  begin
17
5
  require 'hoe'
18
- config = Hoe.new('utilrb', Utilrb::VERSION) do |p|
19
- p.developer("Sylvain Joyeux", "sylvain.joyeux@m4x.org")
20
6
 
21
- p.summary = 'Yet another Ruby toolkit'
22
- p.description = p.paragraphs_of('README.txt', 3..6).join("\n\n")
23
- p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1].map { |l| l.strip }
24
- p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
7
+ hoe_spec = Hoe.spec 'utilrb' do
8
+ developer "Sylvain Joyeux", "sylvain.joyeux@m4x.org"
9
+ extra_deps <<
10
+ ['facets', '>= 2.4.0'] <<
11
+ ['rake', '>= 0']
12
+
13
+ extra_dev_deps <<
14
+ ['flexmock', '>= 0.8.6']
25
15
 
26
- p.extra_deps << ['facets', '>= 2.4.0'] << 'rake'
16
+ self.summary = 'Yet another Ruby toolkit'
17
+ self.description = paragraphs_of('README.txt', 3..5).join("\n\n")
27
18
  end
28
- config.spec.extensions << 'ext/extconf.rb'
29
- rescue LoadError
30
- STDERR.puts "cannot load the Hoe gem. Distribution is disabled"
19
+ hoe_spec.spec.extensions << 'ext/extconf.rb'
20
+ Rake.clear_tasks(/^default$/)
21
+ Rake.clear_tasks(/publish_docs/)
22
+
31
23
  rescue Exception => e
32
- STDERR.puts "cannot load the Hoe gem, or Hoe fails. Distribution is disabled"
33
- STDERR.puts "error message is: #{e.message}"
24
+ if e.message !~ /\.rubyforge/
25
+ STDERR.puts "WARN: cannot load the Hoe gem, or Hoe fails. Publishing tasks are disabled"
26
+ STDERR.puts "WARN: error message is: #{e.message}"
27
+ end
34
28
  end
35
29
 
36
- RUBY = RbConfig::CONFIG['RUBY_INSTALL_NAME']
30
+ task :default => :setup
31
+
37
32
  desc "builds Utilrb's C extension"
38
33
  task :setup do
39
34
  Dir.chdir("ext") do
40
- if !system("#{RUBY} extconf.rb") || !system("make")
35
+ if !system("#{FileUtils::RUBY} extconf.rb") || !system("make")
41
36
  raise "cannot build the C extension"
42
37
  end
43
38
  end
44
39
  FileUtils.ln_sf "../ext/utilrb_ext.so", "lib/utilrb_ext.so"
45
40
  end
46
41
 
42
+ task 'publish_docs' => 'redocs' do
43
+ if !system('./update_github')
44
+ raise "cannot update the gh-pages branch for GitHub"
45
+ end
46
+ if !system('git', 'push', 'github', '+gh-pages')
47
+ raise "cannot push the documentation"
48
+ end
49
+ end
50
+
47
51
  task :clean do
48
52
  puts "Cleaning extension in ext/"
49
53
  FileUtils.rm_f "lib/utilrb_ext.so"
@@ -63,27 +67,3 @@ task :full_test do
63
67
  system("testrb test/")
64
68
  end
65
69
 
66
- task :rcov_test do
67
- Dir.chdir('test') do
68
- if !File.directory?('../rcov')
69
- File.mkdir('../rcov')
70
- end
71
- File.open("../rcov/index.html", "w") do |index|
72
- index.puts <<-EOF
73
- <!DOCTYPE html PUBLIC
74
- "-//W3C//DTD XHTML 1.0 Transitional//EN"
75
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
76
- <body>
77
- EOF
78
-
79
- Dir.glob('test_*.rb').each do |path|
80
- puts "\n" * 4 + "=" * 5 + " #{path} " + "=" * 5 + "\n"
81
- basename = File.basename(path, '.rb')
82
- system("rcov --replace-progname -o ../rcov/#{basename} #{path}")
83
- index.puts "<div class=\"test\"><a href=\"#{basename}/index.html\">#{basename}</a></div>"
84
- end
85
- index.puts "</body>"
86
- end
87
- end
88
- end
89
-
data/ext/extconf.rb CHANGED
@@ -5,6 +5,19 @@ if RUBY_VERSION >= "1.9"
5
5
  $CFLAGS += " -DRUBY_IS_19"
6
6
  end
7
7
 
8
- $LDFLAGS += "-module"
8
+ $LDFLAGS += " -module"
9
9
  create_makefile("utilrb_ext")
10
10
 
11
+ ## WORKAROUND a problem with mkmf.rb
12
+ # It seems that the newest version do define an 'install' target. However, that
13
+ # install target tries to install in the system directories
14
+ #
15
+ # The issue is that RubyGems *does* call make install. Ergo, gem install utilrb
16
+ # is broken right now
17
+ lines = File.readlines("Makefile")
18
+ lines.delete_if { |l| l =~ /^install:/ }
19
+ lines << "install:"
20
+ File.open("Makefile", 'w') do |io|
21
+ io.write lines.join("\n")
22
+ end
23
+
data/ext/value_set.cc CHANGED
@@ -165,6 +165,26 @@ static VALUE value_set_merge(VALUE vself, VALUE vother)
165
165
  return vself;
166
166
  }
167
167
 
168
+ /* call-seq:
169
+ * set.intersection!(other) => set
170
+ *
171
+ * Computes the intersection of +set+ and +other+, and modifies +self+ to be
172
+ * that interesection. This operation is O(N + M) if +other+ is a ValueSet
173
+ */
174
+ static VALUE value_set_intersection_bang(VALUE vself, VALUE vother)
175
+ {
176
+ ValueSet& self = get_wrapped_set(vself);
177
+ if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
178
+ rb_raise(rb_eArgError, "expected a ValueSet");
179
+ ValueSet const& other = get_wrapped_set(vother);
180
+
181
+ ValueSet result;
182
+ std::set_intersection(self.begin(), self.end(), other.begin(), other.end(),
183
+ std::inserter(result, result.end()));
184
+ self.swap(result);
185
+ return vself;
186
+ }
187
+
168
188
  /* call-seq:
169
189
  * set.intersection(other) => intersection_set
170
190
  * set & other => intersection_set
@@ -216,12 +236,32 @@ static VALUE value_set_intersects(VALUE vself, VALUE vother)
216
236
  return Qfalse;
217
237
  }
218
238
 
239
+ /* call-seq:
240
+ * set.difference!(other) => set
241
+ *
242
+ * Modifies +set+ so that it is the set of all elements of +set+ not in +other+.
243
+ * This operation is O(N + M).
244
+ */
245
+ static VALUE value_set_difference_bang(VALUE vself, VALUE vother)
246
+ {
247
+ ValueSet& self = get_wrapped_set(vself);
248
+ if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
249
+ rb_raise(rb_eArgError, "expected a ValueSet");
250
+ ValueSet const& other = get_wrapped_set(vother);
251
+
252
+ ValueSet result;
253
+ std::set_difference(self.begin(), self.end(), other.begin(), other.end(),
254
+ std::inserter(result, result.end()));
255
+ self.swap(result);
256
+ return vself;
257
+ }
258
+
219
259
  /* call-seq:
220
260
  * set.difference(other) => difference_set
221
261
  * set - other => difference_set
222
262
  *
223
263
  * Computes the set of all elements of +set+ not in +other+. This operation
224
- * is O(N + M) if +other+ is a ValueSet
264
+ * is O(N + M).
225
265
  */
226
266
  static VALUE value_set_difference(VALUE vself, VALUE vother)
227
267
  {
@@ -371,8 +411,10 @@ extern "C" void Init_value_set()
371
411
  rb_define_method(cValueSet, "include_all?", RUBY_METHOD_FUNC(value_set_include_all_p), 1);
372
412
  rb_define_method(cValueSet, "union", RUBY_METHOD_FUNC(value_set_union), 1);
373
413
  rb_define_method(cValueSet, "intersection", RUBY_METHOD_FUNC(value_set_intersection), 1);
414
+ rb_define_method(cValueSet, "intersection!", RUBY_METHOD_FUNC(value_set_intersection_bang), 1);
374
415
  rb_define_method(cValueSet, "intersects?", RUBY_METHOD_FUNC(value_set_intersects), 1);
375
416
  rb_define_method(cValueSet, "difference", RUBY_METHOD_FUNC(value_set_difference), 1);
417
+ rb_define_method(cValueSet, "difference!", RUBY_METHOD_FUNC(value_set_difference_bang), 1);
376
418
  rb_define_method(cValueSet, "insert", RUBY_METHOD_FUNC(value_set_insert), 1);
377
419
  rb_define_method(cValueSet, "merge", RUBY_METHOD_FUNC(value_set_merge), 1);
378
420
  rb_define_method(cValueSet, "delete", RUBY_METHOD_FUNC(value_set_delete), 1);
@@ -2,6 +2,7 @@ require 'utilrb/enumerable/to_s_helper'
2
2
  class Array
3
3
  # Displays arrays as [ a, b, [c, d], ... ] instead of the standard #join
4
4
  # Unlike #inspect, it calls #to_s on the elements too
5
+ undef_method :to_s
5
6
  def to_s
6
7
  EnumerableToString.to_s_helper(self, '[', ']') do |obj|
7
8
  obj.to_s
data/lib/utilrb/common.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  module Utilrb
2
2
  unless defined? Utilrb::VERSION
3
- VERSION = "1.3.3"
4
- RUBY_IS_19 = (RUBY_VERSION >= "1.9")
3
+ VERSION = "1.4.0"
4
+ RUBY_IS_19 = (RUBY_VERSION >= "1.9.2")
5
+ RUBY_IS_191 = (RUBY_VERSION >= "1.9") && (RUBY_VERSION < "1.9.2")
5
6
  end
6
7
 
7
8
  unless defined? UTILRB_EXT_MODE
@@ -0,0 +1,78 @@
1
+ module Utilrb
2
+ # Find configuration files within the pathes given
3
+ # by ROCK_CONFIG_PATH environment variable
4
+ #
5
+ class ConfigurationFinder
6
+
7
+ # Find a file by searching through paths defined by an environment variable
8
+ # and a given package directory. Package name is appended to all pathes found
9
+ # in the environment
10
+ #
11
+ # Returns the path to the file on success, otherwise nil
12
+ def self.findWithEnv(filename, pkg_name, environment_search_path)
13
+ if environment_search_path
14
+ env_var = ENV[environment_search_path]
15
+ # Extract search path from environment variable
16
+ configuration_path = Array.new
17
+ env_var.split(':').each do | path |
18
+ # Extract path and append package name folder
19
+ configuration_path << File.join(path.gsub(/:$/,''), pkg_name)
20
+ end
21
+ end
22
+
23
+ if configuration_path == nil
24
+ raise "ConfigurationFinder: Environment variable #{environment_search_path} is not set!\n"
25
+ else
26
+ configuration = search(filename, configuration_path)
27
+ end
28
+
29
+ configuration
30
+ end
31
+
32
+ # Search for a file within [ $ROCK_CONFIG_PATH ]/<packagename>/
33
+ # Will not perform a recursive search
34
+ #
35
+ # Returns the path to the file on success, otherwise nil
36
+ def self.find(filename, pkg_name)
37
+ findWithEnv(filename, pkg_name, 'ROCK_CONFIG_PATH')
38
+ end
39
+
40
+ # Search for a file only in the given search directories
41
+ #
42
+ # Returns the path to the file on success, otherwise nil
43
+ def self.search(filename, search_dirs)
44
+ search_dirs.each do |path|
45
+ file = File.join(path,filename)
46
+ if File.exist?(file)
47
+ return file
48
+ end
49
+ end
50
+ return
51
+ end
52
+
53
+ # Search for a file using the system id (<basename>_<id>)
54
+ #
55
+ # returns the configuration found in [ $ROCK_CONFIG_PATH ]/<basename>/<id>/, performs
56
+ # a fallback search in <basename> and returns nil if no config could
57
+ # be found
58
+ def self.findSystemConfig(filename, system_id)
59
+ id_components = system_id.split('_')
60
+
61
+ if(id_components.size != 2)
62
+ raise "ConfigurationFinder: Invalid system identifier #{system_id} provided. " +
63
+ "Use <basename>_<id>"
64
+ end
65
+
66
+ base_pkg_name = id_components[0]
67
+ id_pkg_name = File.join(base_pkg_name, id_components[1])
68
+ system_config = find(filename, id_pkg_name)
69
+
70
+ if !system_config
71
+ system_config = find(filename, base_pkg_name)
72
+ end
73
+
74
+ system_config
75
+ end
76
+ end
77
+
78
+ end
@@ -0,0 +1,2 @@
1
+ require 'utilrb/kernel/require'
2
+ require_dir(__FILE__)
@@ -0,0 +1,26 @@
1
+ class Hash
2
+ def recursive_merge(hash, &block)
3
+ merge(hash) do |k, v1, v2|
4
+ if v1.kind_of?(Hash) && v2.kind_of?(Hash)
5
+ v1.recursive_merge(v2, &block)
6
+ elsif block_given?
7
+ yield(k, v1, v2)
8
+ else
9
+ v2
10
+ end
11
+ end
12
+ end
13
+
14
+ def recursive_merge!(hash, &block)
15
+ merge!(hash) do |k, v1, v2|
16
+ if v1.kind_of?(Hash) && v2.kind_of?(Hash)
17
+ v1.recursive_merge!(v2, &block)
18
+ elsif block_given?
19
+ yield(k, v1, v2)
20
+ else
21
+ v2
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -2,6 +2,7 @@ require 'utilrb/enumerable/to_s_helper'
2
2
  class Hash
3
3
  # Displays hashes as { a => A, b => B, ... } instead of the standard #join
4
4
  # Unlike #inspect, it calls #to_s on the elements too
5
+ undef_method :to_s
5
6
  def to_s
6
7
  EnumerableToString.to_s_helper(self, '{', '}') do |k, v|
7
8
  "#{k} => #{v}"
@@ -0,0 +1,187 @@
1
+ require 'utilrb/common'
2
+ require 'utilrb/object/singleton_class'
3
+ require 'utilrb/kernel/with_module'
4
+
5
+ module Kernel
6
+ def self.backtrace_remove_first_occurence_of(e, rx)
7
+ # Remove the first occurence of eval_dsl_file_content in the backtrace
8
+ backtrace = e.backtrace.dup
9
+ found = false
10
+ backtrace.delete_if do |line|
11
+ break if found
12
+ line =~ rx
13
+ found = true
14
+ end
15
+ raise e, e.message, e.backtrace
16
+ end
17
+
18
+ def load_dsl_filter_backtrace(file, full_backtrace = false, *exceptions)
19
+ # Compute the position of the dsl-loading method that called us, so that
20
+ # we don't touch anything below that while we are filtering the
21
+ # backtrace
22
+ if !full_backtrace
23
+ callers = caller
24
+ our_frame_pos = caller.size
25
+ callers.each do |line|
26
+ if line != /load_dsl_file\.rb/
27
+ our_frame_pos -= 1
28
+ else
29
+ break
30
+ end
31
+ end
32
+ end
33
+
34
+ yield
35
+
36
+ rescue Exception => e
37
+ raise e if full_backtrace
38
+ if exceptions.any? { |e_class| e.kind_of?(e_class) }
39
+ raise e
40
+ end
41
+
42
+ backtrace = e.backtrace.dup
43
+ message = e.message.dup
44
+
45
+ # Filter out the message ... it can contain backtrace information as
46
+ # well (!)
47
+ message = message.split("\n").map do |line|
48
+ if line =~ /^.*:\d+(:.*)$/
49
+ backtrace.unshift line
50
+ nil
51
+ else
52
+ line
53
+ end
54
+ end.compact.join("\n")
55
+
56
+
57
+ if message.empty?
58
+ message = backtrace.shift
59
+ if message =~ /^(\s*[^\s]+:\d+:)\s*(.*)/
60
+ location = $1
61
+ message = $2
62
+ backtrace.unshift location
63
+ else
64
+ backtrace.unshift message
65
+ end
66
+ end
67
+
68
+ filtered_backtrace = backtrace[0, backtrace.size - our_frame_pos].
69
+ map do |line|
70
+ line.gsub! /:in `.*dsl.*'/, ''
71
+ if line =~ /load_dsl_file.*(method_missing|send)/
72
+ next
73
+ end
74
+
75
+ if line =~ /(load_dsl_file\.rb|with_module\.rb):\d+/
76
+ next
77
+ else
78
+ line
79
+ end
80
+ end.compact
81
+
82
+
83
+ backtrace = (filtered_backtrace[0, 1] + filtered_backtrace + backtrace[(backtrace.size - our_frame_pos)..-1])
84
+ raise e, message, backtrace
85
+ end
86
+
87
+ def eval_dsl_block(block, proxied_object, context, full_backtrace, *exceptions)
88
+ load_dsl_filter_backtrace(nil, full_backtrace, *exceptions) do
89
+ proxied_object.with_module(*context, &block)
90
+ true
91
+ end
92
+ end
93
+
94
+ def eval_dsl_file_content(file, file_content, proxied_object, context, full_backtrace, *exceptions, &block)
95
+ code = with_module(*context) do
96
+ code = <<-EOD
97
+ Proc.new { #{file_content} }
98
+ EOD
99
+ eval code, binding, file, 1
100
+ end
101
+
102
+ dsl_exec_common(file, proxied_object, context, full_backtrace, *exceptions, &code)
103
+ end
104
+
105
+ # Load the given file by eval-ing it in the provided binding. The
106
+ # originality of this method is to translate errors that are detected in the
107
+ # eval'ed code into errors that refer to the provided file
108
+ #
109
+ # The caller of this method should call it at the end of its definition
110
+ # file, or the translation method may not be robust at all
111
+ def eval_dsl_file(file, proxied_object, context, full_backtrace, *exceptions, &block)
112
+ if !File.readable?(file)
113
+ raise ArgumentError, "#{file} does not exist"
114
+ end
115
+
116
+ loaded_file = file.gsub(/^#{Regexp.quote(Dir.pwd)}\//, '')
117
+ file_content = File.read(file)
118
+ eval_dsl_file_content(loaded_file, file_content, proxied_object, context, full_backtrace, *exceptions, &block)
119
+ end
120
+
121
+ # Same than eval_dsl_file, but will not load the same file twice
122
+ def load_dsl_file(file, *args, &block)
123
+ file = File.expand_path(file)
124
+ if $LOADED_FEATURES.include?(file)
125
+ return false
126
+ end
127
+
128
+ eval_dsl_file(file, *args, &block)
129
+ $LOADED_FEATURES << file
130
+ true
131
+ end
132
+
133
+ def dsl_exec(proxied_object, context, full_backtrace, *exceptions, &code)
134
+ dsl_exec_common(nil, proxied_object, context, full_backtrace, *exceptions, &code)
135
+ end
136
+
137
+ def dsl_exec_common(file, proxied_object, context, full_backtrace, *exceptions, &code)
138
+ load_dsl_filter_backtrace(file, full_backtrace, *exceptions) do
139
+ sandbox = with_module(*context) do
140
+ Class.new do
141
+ attr_accessor :main_object
142
+ def initialize(obj); @main_object = obj end
143
+ def method_missing(*m, &block)
144
+ main_object.send(*m, &block)
145
+ end
146
+ end
147
+ end
148
+
149
+ old_constants, new_constants = nil
150
+ if !Utilrb::RUBY_IS_191
151
+ old_constants = Kernel.constants
152
+ end
153
+
154
+ sandbox = sandbox.new(proxied_object)
155
+ sandbox.with_module(*context) do
156
+ old_constants =
157
+ if respond_to?(:constants)
158
+ constants
159
+ else self.class.constants
160
+ end
161
+
162
+ instance_eval(&code)
163
+
164
+ new_constants =
165
+ if respond_to?(:constants)
166
+ constants
167
+ else self.class.constants
168
+ end
169
+ end
170
+
171
+ # Check if the user defined new constants by using class K and/or
172
+ # mod Mod
173
+ if !Utilrb::RUBY_IS_191
174
+ new_constants = Kernel.constants
175
+ end
176
+
177
+ new_constants -= old_constants
178
+ new_constants.delete_if { |n| n.to_s == 'WithModuleConstResolutionExtension' }
179
+ if !new_constants.empty?
180
+ msg = "#{new_constants.first} does not exist. You cannot define new constants in this context"
181
+ raise NameError.new(msg, new_constants.first)
182
+ end
183
+ true
184
+ end
185
+ end
186
+ end
187
+
@@ -17,11 +17,20 @@ module Kernel
17
17
  # filter_options(nil, known_options) -> default_options, {}
18
18
  #
19
19
  def filter_options(options, option_spec)
20
+ unknown_options = Hash.new
21
+ options = options.dup
22
+ options.delete_if do |key, value|
23
+ if !key.respond_to?(:to_sym)
24
+ unknown_options[key] = value
25
+ true
26
+ end
27
+ end
28
+
20
29
  options = (options.to_hash || Hash.new).to_sym_keys
21
30
  # cannot use #to_sym_keys as option_spec can be an array
22
31
  option_spec = option_spec.inject({}) { |h, (k, v)| h[k.to_sym] = v; h }
23
32
 
24
- unknown_options = options.slice(*(options.keys - option_spec.keys))
33
+ unknown_options.merge!(options.slice(*(options.keys - option_spec.keys)))
25
34
  known_options = options.slice(*option_spec.keys)
26
35
 
27
36
  # Set default values defined in the spec