+1 On Jul 26, 2009, at 9:03 AM, Brice Figureau wrote:
> > Those variables have been created to be short lived and used mainly > to define temporary special variables. > They do not persist after a call to unset_ephemeral_var. > Also Scope#set_ephemeral_from can be used to promote a regexp > MatchData to ephemeral values. > > Signed-off-by: Brice Figureau <[email protected]> > --- > lib/puppet/parser/ast/vardef.rb | 2 +- > lib/puppet/parser/scope.rb | 61 +++++++++++++++++++++++ > +---------- > spec/unit/parser/ast/vardef.rb | 4 +- > spec/unit/parser/scope.rb | 68 ++++++++++++++++++++++++++++++ > +++++---- > 4 files changed, 107 insertions(+), 28 deletions(-) > > diff --git a/lib/puppet/parser/ast/vardef.rb b/lib/puppet/parser/ast/ > vardef.rb > index 2d5f623..ae24b32 100644 > --- a/lib/puppet/parser/ast/vardef.rb > +++ b/lib/puppet/parser/ast/vardef.rb > @@ -17,7 +17,7 @@ class Puppet::Parser::AST > value = @value.safeevaluate(scope) > > parsewrap do > - scope.setvar(name,value, @file, @line, @append) > + scope.setvar(name,value, :file => @file, :line => > @line, :append => @append) > end > end > > diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb > index be4dc12..5b3c6d0 100644 > --- a/lib/puppet/parser/scope.rb > +++ b/lib/puppet/parser/scope.rb > @@ -128,6 +128,11 @@ class Puppet::Parser::Scope > # The symbol table for this scope. This is where we store > variables. > @symtable = {} > > + # the ephemeral symbol tables > + # those should not persist long, and are used for the > moment only > + # for $0..$xy capture variables of regexes > + @ephemeral = {} > + > # All of the defaults set for types. It's a hash of hashes, > # with the first key being the type, then the second key being > # the parameter. > @@ -189,16 +194,17 @@ class Puppet::Parser::Scope > # Look up a variable. The simplest value search we do. Default > to returning > # an empty string for missing values, but support returning a > constant. > def lookupvar(name, usestring = true) > + table = ephemeral?(name) ? @ephemeral : @symtable > # If the variable is qualified, then find the specified > scope and look the variable up there instead. > if name =~ /::/ > return lookup_qualified_var(name, usestring) > end > - # We can't use "if @symtable[name]" here because the value > might be false > - if @symtable.include?(name) > - if usestring and @symtable[name] == :undef > + # We can't use "if table[name]" here because the value > might be false > + if table.include?(name) > + if usestring and table[name] == :undef > return "" > else > - return @symtable[name] > + return table[name] > end > elsif self.parent > return parent.lookupvar(name, usestring) > @@ -286,34 +292,35 @@ class Puppet::Parser::Scope > # Set a variable in the current scope. This will override > settings > # in scopes above, but will not allow variables in the current > scope > # to be reassigned. > - def setvar(name,value, file = nil, line = nil, append = false) > + def setvar(name,value, options = {}) > + table = options[:ephemeral] ? @ephemeral : @symtable > #Puppet.debug "Setting %s to '%s' at level %s mode append > %s" % > # [name.inspect,value,self.level, append] > - if @symtable.include?(name) > - unless append > + if table.include?(name) > + unless options[:append] > error = Puppet::ParseError.new("Cannot reassign > variable %s" % name) > else > error = Puppet::ParseError.new("Cannot append, > variable %s is defined in this scope" % name) > end > - if file > - error.file = file > + if options[:file] > + error.file = options[:file] > end > - if line > - error.line = line > + if options[:line] > + error.line = options[:line] > end > raise error > end > > - unless append > - @symtable[name] = value > + unless options[:append] > + table[name] = value > else # append case > # lookup the value in the scope if it exists and insert > the var > - @symtable[name] = lookupvar(name) > + table[name] = lookupvar(name) > # concatenate if string, append if array, nothing for > other types > if value.is_a?(Array) > - @symtable[name] += value > + table[name] += value > else > - @symtable[name] << value > + table[name] << value > end > end > end > @@ -391,8 +398,26 @@ class Puppet::Parser::Scope > > # Undefine a variable; only used for testing. > def unsetvar(var) > - if @symtable.include?(var) > - @symtable.delete(var) > + table = ephemeral?(var) ? @ephemeral : @table > + if table.include?(var) > + table.delete(var) > + end > + end > + > + def unset_ephemeral_var > + @ephemeral = {} > + end > + > + def ephemeral?(name) > + @ephemeral.include?(name) > + end > + > + def ephemeral_from(match, file = nil, line = nil) > + raise(ArgumentError,"Invalid regex match data") unless > match.is_a?(MatchData) > + > + setvar("0", match[0], :file => file, :line => > line, :ephemeral => true) > + match.captures.each_with_index do |m,i| > + setvar("#{i+1}", m, :file => file, :line => > line, :ephemeral => true) > end > end > end > diff --git a/spec/unit/parser/ast/vardef.rb b/spec/unit/parser/ast/ > vardef.rb > index 14de689..9730cee 100755 > --- a/spec/unit/parser/ast/vardef.rb > +++ b/spec/unit/parser/ast/vardef.rb > @@ -25,7 +25,7 @@ describe Puppet::Parser::AST::VarDef do > name = stub 'name', :safeevaluate => "var" > value = stub 'value', :safeevaluate => "1" > > - @scope.expects(:setvar).with { | > name,value,file,line,append| append == nil } > + @scope.expects(:setvar).with { |name,value,options| > options[:append] == nil } > > vardef = Puppet::Parser::AST::VarDef.new :name => > name, :value => value, :file => nil, > :line => nil > @@ -36,7 +36,7 @@ describe Puppet::Parser::AST::VarDef do > name = stub 'name', :safeevaluate => "var" > value = stub 'value', :safeevaluate => "1" > > - @scope.expects(:setvar).with { | > name,value,file,line,append| append == true } > + @scope.expects(:setvar).with { |name,value,options| > options[:append] == true } > > vardef = Puppet::Parser::AST::VarDef.new :name => > name, :value => value, :file => nil, > :line => > nil, :append => true > diff --git a/spec/unit/parser/scope.rb b/spec/unit/parser/scope.rb > index a9784e0..641a3f9 100755 > --- a/spec/unit/parser/scope.rb > +++ b/spec/unit/parser/scope.rb > @@ -111,24 +111,24 @@ describe Puppet::Parser::Scope do > > describe "when setvar is called with append=true" do > it "should raise error if the variable is already defined in > this scope" do > - @scope.setvar("var","1",nil,nil,false) > - lambda { @scope.setvar("var","1",nil,nil,true) }.should > raise_error(Puppet::ParseError) > + @scope.setvar("var","1", :append => false) > + lambda { @scope.setvar("var","1", :append => > true) }.should raise_error(Puppet::ParseError) > end > > it "it should lookup current variable value" do > @scope.expects(:lookupvar).with("var").returns("2") > - @scope.setvar("var","1",nil,nil,true) > + @scope.setvar("var","1", :append => true) > end > > it "it should store the concatenated string '42'" do > - @topscope.setvar("var","4",nil,nil,false) > - @scope.setvar("var","2",nil,nil,true) > + @topscope.setvar("var","4", :append => false) > + @scope.setvar("var","2", :append => true) > @scope.lookupvar("var").should == "42" > end > > it "it should store the concatenated array [4,2]" do > - @topscope.setvar("var",[4],nil,nil,false) > - @scope.setvar("var",[2],nil,nil,true) > + @topscope.setvar("var",[4], :append => false) > + @scope.setvar("var",[2], :append => true) > @scope.lookupvar("var").should == [4,2] > end > > @@ -195,4 +195,58 @@ describe Puppet::Parser::Scope do > Puppet::Parser::Scope.number?("0x89g").should be_nil > end > end > + > + describe "when using ephemeral variables" do > + it "should store the variable value" do > + @scope.setvar("1", :value, :ephemeral => true) > + > + @scope.lookupvar("1").should == :value > + end > + > + it "should remove the variable value when > unset_ephemeral_var is called" do > + @scope.setvar("1", :value, :ephemeral => true) > + @scope.stubs(:parent).returns(nil) > + > + @scope.unset_ephemeral_var > + > + @scope.lookupvar("1", false).should == :undefined > + end > + > + it "should not remove classic variables when > unset_ephemeral_var is called" do > + @scope.setvar("myvar", :value1) > + @scope.setvar("1", :value2, :ephemeral => true) > + @scope.stubs(:parent).returns(nil) > + > + @scope.unset_ephemeral_var > + > + @scope.lookupvar("myvar", false).should == :value1 > + end > + end > + > + describe "when setting ephemeral vars from matches" do > + before :each do > + @match = stub 'match', :is_a? => true > + @match.stubs(:[]).with(0).returns("this is a string") > + @match.stubs(:captures).returns([]) > + @scope.stubs(:setvar) > + end > + > + it "should accept only MatchData" do > + lambda { @scope.ephemeral_from("match") }.should > raise_error > + end > + > + it "should set $0 with the full match" do > + @scope.expects(:setvar).with { |*arg| arg[0] == "0" and > arg[1] == "this is a string" and arg[2][:ephemeral] } > + > + @scope.ephemeral_from(@match) > + end > + > + it "should set every capture as ephemeral var" do > + @match.stubs(:captures).returns([:capture1,:capture2]) > + @scope.expects(:setvar).with { |*arg| arg[0] == "1" and > arg[1] == :capture1 and arg[2][:ephemeral] } > + @scope.expects(:setvar).with { |*arg| arg[0] == "2" and > arg[1] == :capture2 and arg[2][:ephemeral] } > + > + @scope.ephemeral_from(@match) > + end > + end > end > -- > 1.6.0.2 > > > > -- Discovery consists of seeing what everybody has seen and thinking what nobody has thought. -- Albert Szent-Gyorgyi --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en -~----------~----~----~----~------~----~------~--~---
