utilrb 1.3.3 → 1.4.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.
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