0002-Changed-indentation-to-be-more-consistent-with-style.patch

Ian Taylor, 06/05/2009 04:13 pm

Download (99.3 kB)

b/autotest/discover.rb
1 1
require 'autotest'
2 2

  
3 3
Autotest.add_discovery do
4
  "rspec"
4
    "rspec"
5 5
end
6 6

  
7 7
Autotest.add_discovery do
8
  "puppet"
8
    "puppet"
9 9
end
b/autotest/rspec.rb
1 1
require 'autotest'
2 2

  
3 3
Autotest.add_hook :initialize do |at|
4
  at.clear_mappings
5
  # watch out: Ruby bug (1.8.6):
6
  # %r(/) != /\//
7
  at.add_mapping(%r%^spec/.*\.rb$%) { |filename, _| 
8
    filename 
9
  }
10
  at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m| 
11
    ["spec/#{m[1]}_spec.rb"]
12
  }
13
  at.add_mapping(%r%^spec/(spec_helper|shared/.*)\.rb$%) { 
14
    at.files_matching %r{^spec/.*_spec\.rb$}
15
  }
4
    at.clear_mappings
5
    # watch out: Ruby bug (1.8.6):
6
    # %r(/) != /\//
7
    at.add_mapping(%r%^spec/.*\.rb$%) { |filename, _|
8
        filename
9
    }
10
    at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m|
11
        ["spec/#{m[1]}_spec.rb"]
12
    }
13
    at.add_mapping(%r%^spec/(spec_helper|shared/.*)\.rb$%) {
14
        at.files_matching %r{^spec/.*_spec\.rb$}
15
    }
16 16
end
17 17

  
18 18
class RspecCommandError < StandardError; end
19 19

  
20 20
class Autotest::Rspec < Autotest
21 21

  
22
  def initialize
23
    super
22
    def initialize
23
        super
24 24

  
25
    self.failed_results_re = /^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m
26
    self.completed_re = /\Z/ # FIX: some sort of summary line at the end?
27
  end
25
        self.failed_results_re = /^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m
26
        self.completed_re = /\Z/ # FIX: some sort of summary line at the end?
27
    end
28 28

  
29
  def consolidate_failures(failed)
30
    filters = Hash.new { |h,k| h[k] = [] }
31
    failed.each do |spec, failed_trace|
32
      if f = test_files_for(failed).find { |f| failed_trace =~ Regexp.new(f) } then
33
        filters[f] << spec
34
        break
35
      end
29
    def consolidate_failures(failed)
30
        filters = Hash.new { |h,k| h[k] = [] }
31
        failed.each do |spec, failed_trace|
32
            if f = test_files_for(failed).find { |f| failed_trace =~ Regexp.new(f) } then
33
                filters[f] << spec
34
                break
35
            end
36
        end
37
        return filters
36 38
    end
37
    return filters
38
  end
39 39

  
40
  def make_test_cmd(files_to_test)
41
    return "#{ruby} -S #{spec_command} #{add_options_if_present} #{files_to_test.keys.flatten.join(' ')}"
42
  end
43
  
44
  def add_options_if_present
45
    File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : ""
46
  end
40
    def make_test_cmd(files_to_test)
41
        return "#{ruby} -S #{spec_command} #{add_options_if_present} #{files_to_test.keys.flatten.join(' ')}"
42
    end
47 43

  
48
  # Finds the proper spec command to use.  Precendence is set in the
49
  # lazily-evaluated method spec_commands.  Alias + Override that in
50
  # ~/.autotest to provide a different spec command then the default
51
  # paths provided.
52
  def spec_command(separator=File::ALT_SEPARATOR)
53
    unless defined? @spec_command then
54
      @spec_command = spec_commands.find { |cmd| File.exists? cmd }
44
    def add_options_if_present
45
        File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : ""
46
    end
55 47

  
56
      raise RspecCommandError, "No spec command could be found!" unless @spec_command
48
    # Finds the proper spec command to use.  Precendence is set in the
49
    # lazily-evaluated method spec_commands.  Alias + Override that in
50
    # ~/.autotest to provide a different spec command then the default
51
    # paths provided.
52
    def spec_command(separator=File::ALT_SEPARATOR)
53
        unless defined? @spec_command then
54
            @spec_command = spec_commands.find { |cmd| File.exists? cmd }
57 55

  
58
      @spec_command.gsub! File::SEPARATOR, separator if separator
56
            raise RspecCommandError, "No spec command could be found!" unless @spec_command
57

  
58
            @spec_command.gsub! File::SEPARATOR, separator if separator
59
        end
60
        @spec_command
59 61
    end
60
    @spec_command
61
  end
62 62

  
63
  # Autotest will look for spec commands in the following
64
  # locations, in this order:
65
  #
66
  #   * bin/spec
67
  #   * default spec bin/loader installed in Rubygems
68
  def spec_commands
69
    [
70
      File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec')),
71
      File.join(Config::CONFIG['bindir'], 'spec')
72
    ]
73
  end
63
    # Autotest will look for spec commands in the following
64
    # locations, in this order:
65
    #
66
    #   * bin/spec
67
    #   * default spec bin/loader installed in Rubygems
68
    def spec_commands
69
        [
70
            File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec')),
71
            File.join(Config::CONFIG['bindir'], 'spec')
72
        ]
73
    end
74 74
end
b/ext/nagios/check_puppet.rb
6 6

  
7 7
class CheckPuppet
8 8

  
9
  VERSION = '0.1'
10
  script_name = File.basename($0)
11

  
12
  # default options
13
  OPTIONS = {
14
     :statefile   => "/var/puppet/state/state.yaml",
15
     :process     => "puppetd",
16
     :interval    => 30,
17
  }
18

  
19
  o = OptionParser.new do |o|    
20
    o.set_summary_indent('  ')
21
    o.banner =    "Usage: #{script_name} [OPTIONS]"
22
    o.define_head "The check_puppet Nagios plug-in checks that specified " +
9
    VERSION = '0.1'
10
    script_name = File.basename($0)
11

  
12
    # default options
13
    OPTIONS = {
14
        :statefile => "/var/puppet/state/state.yaml",
15
        :process   => "puppetd",
16
        :interval  => 30,
17
    }
18

  
19
    o = OptionParser.new do |o|
20
        o.set_summary_indent('  ')
21
        o.banner =    "Usage: #{script_name} [OPTIONS]"
22
        o.define_head "The check_puppet Nagios plug-in checks that specified " +
23 23
                  "Puppet process is running and the state file is no " +
24 24
                  "older than specified interval."
25
    o.separator   ""
26
    o.separator   "Mandatory arguments to long options are mandatory for " +
25
                  o.separator   ""
26
                  o.separator   "Mandatory arguments to long options are mandatory for " +
27 27
                  "short options too."
28
  
29
    o.on("-s", "--statefile=statefile", String, "The state file",
28

  
29
                  o.on("-s", "--statefile=statefile", String, "The state file",
30 30
         "Default: #{OPTIONS[:statefile]}") { |OPTIONS[:statefile]| }
31
    o.on("-p", "--process=processname", String, "The process to check",
31
         o.on("-p", "--process=processname", String, "The process to check",
32 32
         "Default: #{OPTIONS[:process]}")   { |OPTIONS[:process]| }
33
    o.on("-i", "--interval=value", Integer, 
33
         o.on("-i", "--interval=value", Integer,
34 34
         "Default: #{OPTIONS[:interval]} minutes")  { |OPTIONS[:interval]| }
35
     
36
    o.separator ""
37
    o.on_tail("-h", "--help", "Show this help message.") do 
38
      puts o
39
      exit  
40
    end
41
  
42
    o.parse!(ARGV)
43
   end
44 35

  
45
  def check_proc
36
         o.separator ""
37
         o.on_tail("-h", "--help", "Show this help message.") do
38
             puts o
39
             exit
40
         end
46 41

  
47
    unless ProcTable.ps.find { |p| p.name == OPTIONS[:process]}
48
      @proc = 2
49
    else
50
      @proc = 0 
42
         o.parse!(ARGV)
51 43
    end
52
  
53
  end
54 44

  
55
  def check_state
45
    def check_proc
56 46

  
57
    # Set variables
58
    curt = Time.now
59
    intv = OPTIONS[:interval] * 60
47
        unless ProcTable.ps.find { |p| p.name == OPTIONS[:process]}
48
            @proc = 2
49
        else
50
            @proc = 0
51
        end
60 52

  
61
    # Check file time
62
    begin
63
      @modt = File.mtime("#{OPTIONS[:statefile]}")
64
    rescue
65
      @file = 3
66 53
    end
67
 
68
    diff = (curt - @modt).to_i
69 54

  
70
    if diff > intv
71
      @file = 2
72
    else
73
      @file = 0
74
    end
55
    def check_state
75 56

  
76
  end
77

  
78
  def output_status
79
   
80
    case @file
81
    when 0
82
      state = "state file status okay updated on " + @modt.strftime("%m/%d/%Y at %H:%M:%S")
83
    when 2
84
      state = "state fille is not up to date and is older than #{OPTIONS[:interval]} minutes"
85
    when 3
86
      state = "state file status unknown"
87
    end
57
        # Set variables
58
        curt = Time.now
59
        intv = OPTIONS[:interval] * 60
88 60

  
89
    case @proc
90
    when 0
91
      process = "process #{OPTIONS[:process]} is running"
92
    when 2
93
      process = "process #{OPTIONS[:process]} is not running" 
94
    end
61
        # Check file time
62
        begin
63
            @modt = File.mtime("#{OPTIONS[:statefile]}")
64
        rescue
65
            @file = 3
66
        end
67

  
68
        diff = (curt - @modt).to_i
69

  
70
        if diff > intv
71
            @file = 2
72
        else
73
            @file = 0
74
        end
95 75

  
96
    case @proc or @file
97
    when 0
98
      status = "OK"
99
      exitcode = 0
100
    when 2
101
      status = "CRITICAL"
102
      exitcode = 2
103
    when 3
104
      status = "UNKNOWN"
105
      exitcide = 3
106 76
    end
107 77

  
108
    puts "PUPPET " + status + ": " + process + ", " + state
109
    exit(exitcode)
110
 end
78
    def output_status
79

  
80
        case @file
81
        when 0
82
            state = "state file status okay updated on " + @modt.strftime("%m/%d/%Y at %H:%M:%S")
83
        when 2
84
            state = "state fille is not up to date and is older than #{OPTIONS[:interval]} minutes"
85
        when 3
86
            state = "state file status unknown"
87
        end
88

  
89
        case @proc
90
        when 0
91
            process = "process #{OPTIONS[:process]} is running"
92
        when 2
93
            process = "process #{OPTIONS[:process]} is not running"
94
        end
95

  
96
        case @proc or @file
97
        when 0
98
            status = "OK"
99
            exitcode = 0
100
        when 2
101
            status = "CRITICAL"
102
            exitcode = 2
103
        when 3
104
            status = "UNKNOWN"
105
            exitcide = 3
106
        end
107

  
108
        puts "PUPPET " + status + ": " + process + ", " + state
109
        exit(exitcode)
110
    end
111 111
end
112 112

  
113 113
cp = CheckPuppet.new
b/ext/puppetlisten/puppetlisten.rb
25 25
allowed_servers = Array.new
26 26
runner = false;
27 27
File.open(Puppet[:authconfig]).each do |line|
28
  case line
29
  when /^\s*#/: next # skip comments
30
  when /^\s*$/: next # skip blank lines
31
  when /\[puppetrunner\]/: # puppetrunner section
32
    runner=true
33
  when /^\s*(\w+)\s+(.+)$/:
34
    var = $1
35
    value = $2
36
    case var
37
    when "allow":
38
      value.split(/\s*,\s*/).each { |val|
39
      allowed_servers << val
40
      puts "allowing %s access" % val
41
    } if runner==true
28
    case line
29
    when /^\s*#/: next # skip comments
30
    when /^\s*$/: next # skip blank lines
31
    when /\[puppetrunner\]/: # puppetrunner section
32
        runner=true
33
    when /^\s*(\w+)\s+(.+)$/:
34
        var = $1
35
        value = $2
36
        case var
37
        when "allow":
38
            value.split(/\s*,\s*/).each { |val|
39
            allowed_servers << val
40
            puts "allowing %s access" % val
41
        } if runner==true
42
        end
43
    else
44
        runner=false
42 45
    end
43
  else
44
    runner=false
45
  end
46 46
end
47 47

  
48 48
# be a daemon
......
50 50
ssls = OpenSSL::SSL::SSLServer.new(sock, ctx)
51 51

  
52 52
loop do
53
  begin
54
    ns = ssls.accept # start SSL session
55
    af, port, host, ip = ns.peeraddr
56
    print "connection from #{host+"("+ip+")"} "
57
    if allowed_servers.include?(host)
58
      #TODO add support for tags and other command line arguments
59
      puts "accepted"
60
      ns.puts "Executing #{cmd} on #{Facter.fqdn}.\n*******OUTPUT********\n\n"
61
      IO.popen(cmd) do |f|
62
        while line = f.gets do
63
          ns.puts line
53
    begin
54
        ns = ssls.accept # start SSL session
55
        af, port, host, ip = ns.peeraddr
56
        print "connection from #{host+"("+ip+")"} "
57
        if allowed_servers.include?(host)
58
            #TODO add support for tags and other command line arguments
59
            puts "accepted"
60
            ns.puts "Executing #{cmd} on #{Facter.fqdn}.\n*******OUTPUT********\n\n"
61
            IO.popen(cmd) do |f|
62
                while line = f.gets do
63
                    ns.puts line
64
                end
65
            end
66
            ns.puts "\n*********DONE**********"
67
        else
68
            ns.puts "denied\n"
69
            puts "denied"
64 70
        end
65
      end
66
      ns.puts "\n*********DONE**********"
67
    else
68
      ns.puts "denied\n"
69
      puts "denied"
71
        ns.close
72
    rescue
73
        ns.close
74
        next
70 75
    end
71
    ns.close
72
  rescue
73
    ns.close
74
    next
75
  end
76 76
end
b/ext/puppetlisten/puppetrun.rb
6 6

  
7 7
port = 8139
8 8
if ARGV[0].nil?
9
  warn "Usage: hostname to run against"
10
  exit 1
9
    warn "Usage: hostname to run against"
10
    exit 1
11 11
else
12
  host = ARGV[0]
12
    host = ARGV[0]
13 13
end
14 14

  
15 15
require 'puppet/sslcertificates/support'
......
33 33
ssl.sync_close = true  # if true the underlying socket will be
34 34
                       # closed in SSLSocket#close. (default: false)
35 35
while (line = ssl.gets)
36
  puts line
36
    puts line
37 37
end
38 38

  
39 39
ssl.close
b/ext/puppetstoredconfigclean.rb
57 57
args = {:adapter => adapter, :log_level => pm_conf[:rails_loglevel]}
58 58

  
59 59
case adapter
60
  when "sqlite3"
61
    args[:dbfile] = pm_conf[:dblocation]
62
  when "mysql", "postgresql"
63
    args[:host]     = pm_conf[:dbserver] unless pm_conf[:dbserver].to_s.empty?
64
    args[:username] = pm_conf[:dbuser] unless pm_conf[:dbuser].to_s.empty?
65
    args[:password] = pm_conf[:dbpassword] unless pm_conf[:dbpassword].to_s.empty?
66
    args[:database] = pm_conf[:dbname] unless pm_conf[:dbname].to_s.empty?
67
    socket          = pm_conf[:dbsocket]
68
    args[:socket]   = socket unless socket.to_s.empty?
69
  else
70
    raise ArgumentError, "Invalid db adapter %s" % adapter
60
    when "sqlite3"
61
        args[:dbfile] = pm_conf[:dblocation]
62
    when "mysql", "postgresql"
63
        args[:host]     = pm_conf[:dbserver] unless pm_conf[:dbserver].to_s.empty?
64
        args[:username] = pm_conf[:dbuser] unless pm_conf[:dbuser].to_s.empty?
65
        args[:password] = pm_conf[:dbpassword] unless pm_conf[:dbpassword].to_s.empty?
66
        args[:database] = pm_conf[:dbname] unless pm_conf[:dbname].to_s.empty?
67
        socket          = pm_conf[:dbsocket]
68
        args[:socket]   = socket unless socket.to_s.empty?
69
    else
70
        raise ArgumentError, "Invalid db adapter %s" % adapter
71 71
end
72 72

  
73 73
args[:database] = "puppet" unless not args[:database].to_s.empty?
b/lib/puppet/external/dot.rb
8 8

  
9 9
module DOT
10 10
    
11
  # These glogal vars are used to make nice graph source.
11
    # These glogal vars are used to make nice graph source.
12 12

  
13
  $tab  = '    '
14
  $tab2 = $tab * 2
13
    $tab  = '    '
14
    $tab2 = $tab * 2
15 15
    
16
  # if we don't like 4 spaces, we can change it any time
16
    # if we don't like 4 spaces, we can change it any time
17 17

  
18
  def change_tab (t)
19
    $tab  = t
20
    $tab2 = t * 2
21
  end
18
    def change_tab (t)
19
        $tab  = t
20
        $tab2 = t * 2
21
    end
22 22
    
23
  # options for node declaration
24

  
25
  NODE_OPTS = [
26
    # attributes due to
27
    # http://www.graphviz.org/Documentation/dotguide.pdf
28
    # March, 26, 2005
29
    'bottomlabel', # auxiliary label for nodes of shape M*
30
    'color', # default: black; node shape color
31
    'comment', # any string (format-dependent)
32
    'distortion', # default: 0.0; node distortion for shape=polygon
33
    'fillcolor', # default: lightgrey/black; node fill color
34
    'fixedsize', # default: false; label text has no affect on node size
35
    'fontcolor', # default: black; type face color
36
    'fontname', # default: Times-Roman; font family
37
    'fontsize', #default: 14; point size of label
38
    'group', # name of node?s group
39
    'height', # default: .5; height in inches
40
    'label', # default: node name; any string
41
    'layer', # default: overlay range; all, id or id:id
42
    'orientation', # dafault: 0.0; node rotation angle
43
    'peripheries', # shape-dependent number of node boundaries
44
    'regular', # default:  false; force polygon to be regular
45
    'shape', # default: ellipse; node shape; see Section 2.1 and Appendix E
46
    'shapefile', # external EPSF or SVG custom shape file
47
    'sides', # default: 4; number of sides for shape=polygon
48
    'skew' , # default: 0.0; skewing of node for shape=polygon
49
    'style', # graphics options, e.g. bold, dotted, filled; cf. Section 2.3
50
    'toplabel', # auxiliary label for nodes of shape M*
51
    'URL', # URL associated with node (format-dependent)
52
    'width', # default: .75; width in inches
53
    'z', #default: 0.0; z coordinate for VRML output
54

  
55
    # maintained for backward compatibility or rdot internal
56
    'bgcolor',
57
    'rank'
58
  ]
23
    # options for node declaration
24

  
25
    NODE_OPTS = [
26
        # attributes due to
27
        # http://www.graphviz.org/Documentation/dotguide.pdf
28
        # March, 26, 2005
29
        'bottomlabel', # auxiliary label for nodes of shape M*
30
        'color',       # default: black; node shape color
31
        'comment',     # any string (format-dependent)
32
        'distortion',  # default: 0.0; node distortion for shape=polygon
33
        'fillcolor',   # default: lightgrey/black; node fill color
34
        'fixedsize',   # default: false; label text has no affect on node size
35
        'fontcolor',   # default: black; type face color
36
        'fontname',    # default: Times-Roman; font family
37
        'fontsize',    # default: 14; point size of label
38
        'group',       # name of node?s group
39
        'height',      # default: .5; height in inches
40
        'label',       # default: node name; any string
41
        'layer',       # default: overlay range; all, id or id:id
42
        'orientation', # dafault: 0.0; node rotation angle
43
        'peripheries', # shape-dependent number of node boundaries
44
        'regular',     # default:  false; force polygon to be regular
45
        'shape',       # default: ellipse; node shape; see Section 2.1 and Appendix E
46
        'shapefile',   # external EPSF or SVG custom shape file
47
        'sides',       # default: 4; number of sides for shape=polygon
48
        'skew' ,       # default: 0.0; skewing of node for shape=polygon
49
        'style',       # graphics options, e.g. bold, dotted, filled; cf. Section 2.3
50
        'toplabel',    # auxiliary label for nodes of shape M*
51
        'URL',         # URL associated with node (format-dependent)
52
        'width',       # default: .75; width in inches
53
        'z',           # default: 0.0; z coordinate for VRML output
54

  
55
        # maintained for backward compatibility or rdot internal
56
        'bgcolor',
57
        'rank'
58
    ]
59 59
    
60
  # options for edge declaration
61

  
62
  EDGE_OPTS = [
63
    'arrowhead', # default: normal; style of arrowhead at head end
64
    'arrowsize', # default: 1.0; scaling factor for arrowheads
65
    'arrowtail', # default: normal; style of arrowhead at tail end
66
    'color', # default: black; edge stroke color
67
    'comment', # any string (format-dependent)
68
    'constraint', # default: true use edge to affect node ranking
69
    'decorate', # if set, draws a line connecting labels with their edges
70
    'dir', # default: forward; forward, back, both, or none
71
    'fontcolor', # default: black type face color
72
    'fontname', # default: Times-Roman; font family
73
    'fontsize', # default: 14; point size of label
74
    'headlabel', # label placed near head of edge
75
    'headport', # n,ne,e,se,s,sw,w,nw
76
    'headURL', # URL attached to head label if output format is ismap
77
    'label', # edge label
78
    'labelangle', # default: -25.0; angle in degrees which head or tail label is rotated off edge
79
    'labeldistance', # default: 1.0; scaling factor for distance of head or tail label from node
80
    'labelfloat', # default: false; lessen constraints on edge label placement
81
    'labelfontcolor', # default: black; type face color for head and tail labels
82
    'labelfontname', # default: Times-Roman; font family for head and tail labels
83
    'labelfontsize', # default: 14 point size for head and tail labels
84
    'layer', # default: overlay range; all, id or id:id
85
    'lhead', # name of cluster to use as head of edge
86
    'ltail', # name of cluster to use as tail of edge
87
    'minlen', # default: 1 minimum rank distance between head and tail
88
    'samehead', # tag for head node; edge heads with the same tag are merged onto the same port
89
    'sametail', # tag for tail node; edge tails with the same tag are merged onto the same port
90
    'style', # graphics options, e.g. bold, dotted, filled; cf. Section 2.3
91
    'taillabel', # label placed near tail of edge
92
    'tailport', # n,ne,e,se,s,sw,w,nw
93
    'tailURL', # URL attached to tail label if output format is ismap
94
    'weight', # default: 1; integer cost of stretching an edge
95

  
96
    # maintained for backward compatibility or rdot internal
97
    'id'
98
  ]
60
    # options for edge declaration
61

  
62
    EDGE_OPTS = [
63
        'arrowhead',      # default: normal; style of arrowhead at head end
64
        'arrowsize',      # default: 1.0; scaling factor for arrowheads
65
        'arrowtail',      # default: normal; style of arrowhead at tail end
66
        'color',          # default: black; edge stroke color
67
        'comment',        # any string (format-dependent)
68
        'constraint',     # default: true use edge to affect node ranking
69
        'decorate',       # if set, draws a line connecting labels with their edges
70
        'dir',            # default: forward; forward, back, both, or none
71
        'fontcolor',      # default: black type face color
72
        'fontname',       # default: Times-Roman; font family
73
        'fontsize',       # default: 14; point size of label
74
        'headlabel',      # label placed near head of edge
75
        'headport',       # n,ne,e,se,s,sw,w,nw
76
        'headURL',        # URL attached to head label if output format is ismap
77
        'label',          # edge label
78
        'labelangle',     # default: -25.0; angle in degrees which head or tail label is rotated off edge
79
        'labeldistance',  # default: 1.0; scaling factor for distance of head or tail label from node
80
        'labelfloat',     # default: false; lessen constraints on edge label placement
81
        'labelfontcolor', # default: black; type face color for head and tail labels
82
        'labelfontname',  # default: Times-Roman; font family for head and tail labels
83
        'labelfontsize',  # default: 14 point size for head and tail labels
84
        'layer',          # default: overlay range; all, id or id:id
85
        'lhead',          # name of cluster to use as head of edge
86
        'ltail',          # name of cluster to use as tail of edge
87
        'minlen',         # default: 1 minimum rank distance between head and tail
88
        'samehead',       # tag for head node; edge heads with the same tag are merged onto the same port
89
        'sametail',       # tag for tail node; edge tails with the same tag are merged onto the same port
90
        'style',          # graphics options, e.g. bold, dotted, filled; cf. Section 2.3
91
        'taillabel',      # label placed near tail of edge
92
        'tailport',       # n,ne,e,se,s,sw,w,nw
93
        'tailURL',        # URL attached to tail label if output format is ismap
94
        'weight',         # default: 1; integer cost of stretching an edge
95

  
96
        # maintained for backward compatibility or rdot internal
97
        'id'
98
    ]
99 99
    
100
  # options for graph declaration
101

  
102
  GRAPH_OPTS = [
103
    'bgcolor',
104
    'center', 'clusterrank', 'color', 'concentrate',
105
    'fontcolor', 'fontname', 'fontsize',
106
    'label', 'layerseq',
107
    'margin', 'mclimit',
108
    'nodesep', 'nslimit',
109
    'ordering', 'orientation',
110
    'page',
111
    'rank', 'rankdir', 'ranksep', 'ratio',
112
    'size'
113
  ]
100
    # options for graph declaration
101

  
102
    GRAPH_OPTS = [
103
        'bgcolor',
104
        'center', 'clusterrank', 'color', 'concentrate',
105
        'fontcolor', 'fontname', 'fontsize',
106
        'label', 'layerseq',
107
        'margin', 'mclimit',
108
        'nodesep', 'nslimit',
109
        'ordering', 'orientation',
110
        'page',
111
        'rank', 'rankdir', 'ranksep', 'ratio',
112
        'size'
113
    ]
114 114
    
115
  # a root class for any element in dot notation
115
    # a root class for any element in dot notation
116 116

  
117
  class DOTSimpleElement
117
    class DOTSimpleElement
118 118

  
119
    attr_accessor :name
119
        attr_accessor :name
120 120

  
121
    def initialize (params = {})
122
      @label = params['name'] ? params['name'] : ''
123
    end
121
        def initialize (params = {})
122
            @label = params['name'] ? params['name'] : ''
123
        end
124 124

  
125
    def to_s
126
      @name
125
        def to_s
126
            @name
127
        end
127 128
    end
128
  end
129 129
    
130
  # an element that has options ( node, edge, or graph )
131

  
132
  class DOTElement < DOTSimpleElement
133

  
134
    # attr_reader :parent
135
    attr_accessor :name, :options
136

  
137
    def initialize (params = {}, option_list = [])
138
      super(params)
139
      @name   = params['name']   ? params['name']   : nil 
140
      @parent = params['parent'] ? params['parent'] : nil
141
      @options = {}
142
      option_list.each{ |i|
143
        @options[i] = params[i] if params[i]
144
      }
145
      @options['label'] ||= @name if @name != 'node'
146
    end
147
        
148
    def each_option
149
      @options.each{ |i| yield i }
150
    end
130
    # an element that has options ( node, edge, or graph )
151 131

  
152
    def each_option_pair
153
      @options.each_pair{ |key, val| yield key, val }
154
    end
132
    class DOTElement < DOTSimpleElement
133

  
134
        # attr_reader :parent
135
        attr_accessor :name, :options
136

  
137
        def initialize (params = {}, option_list = [])
138
            super(params)
139
            @name   = params['name']   ? params['name']   : nil
140
            @parent = params['parent'] ? params['parent'] : nil
141
            @options = {}
142
            option_list.each{ |i|
143
                @options[i] = params[i] if params[i]
144
            }
145
            @options['label'] ||= @name if @name != 'node'
146
        end
147

  
148
        def each_option
149
            @options.each{ |i| yield i }
150
        end
151

  
152
        def each_option_pair
153
            @options.each_pair{ |key, val| yield key, val }
154
        end
155 155

  
156
    #def parent=( thing )
157
    #    @parent.delete( self ) if defined?( @parent ) and @parent
158
    #    @parent = thing
159
    #end
156
        #def parent=( thing )
157
        #    @parent.delete( self ) if defined?( @parent ) and @parent
158
        #    @parent = thing
159
        #end
160 160

  
161
  end
161
    end
162 162
    
163 163
    
164
  # This is used when we build nodes that have shape=record
165
  # ports don't have options :)
164
    # This is used when we build nodes that have shape=record
165
    # ports don't have options :)
166 166

  
167
  class DOTPort < DOTSimpleElement
167
    class DOTPort < DOTSimpleElement
168 168

  
169
    attr_accessor :label
170
        
171
    def initialize (params = {})
172
      super(params)
173
      @name = params['label'] ? params['label'] : ''
174
    end
169
        attr_accessor :label
175 170

  
176
    def to_s
177
      ( @name && @name != "" ? "<#{@name}>" : "" ) + "#{@label}"
171
        def initialize (params = {})
172
            super(params)
173
            @name = params['label'] ? params['label'] : ''
174
        end
175

  
176
        def to_s
177
            ( @name && @name != "" ? "<#{@name}>" : "" ) + "#{@label}"
178
        end
178 179
    end
179
  end
180 180
    
181
  # node element
181
    # node element
182 182

  
183
  class DOTNode < DOTElement
183
    class DOTNode < DOTElement
184 184

  
185
    @ports
185
        @ports
186 186

  
187
    def initialize (params = {}, option_list = NODE_OPTS)
188
      super(params, option_list)
189
      @ports = params['ports'] ? params['ports'] : []
190
    end
187
        def initialize (params = {}, option_list = NODE_OPTS)
188
            super(params, option_list)
189
            @ports = params['ports'] ? params['ports'] : []
190
        end
191 191

  
192
    def each_port
193
      @ports.each { |i| yield i }
194
    end
192
        def each_port
193
            @ports.each { |i| yield i }
194
        end
195 195

  
196
    def << (thing)
197
      @ports << thing
198
    end
196
        def << (thing)
197
            @ports << thing
198
        end
199 199

  
200
    def push (thing)
201
      @ports.push(thing)
202
    end
200
        def push (thing)
201
            @ports.push(thing)
202
        end
203 203

  
204
    def pop
205
      @ports.pop
206
    end
204
        def pop
205
            @ports.pop
206
        end
207 207

  
208
    def to_s (t = '')
208
        def to_s (t = '')
209 209

  
210
      # This code is totally incomprehensible; it needs to be replaced!
210
            # This code is totally incomprehensible; it needs to be replaced!
211 211

  
212
      label = @options['shape'] != 'record' && @ports.length == 0 ?
213
                @options['label'] ? 
214
                    t + $tab + "label = \"#{@options['label']}\"\n" :
215
                    '' :
216
                t + $tab + 'label = "' + " \\\n" +
217
                t + $tab2 + "#{@options['label']}| \\\n" +
218
                @ports.collect{ |i|
219
                    t + $tab2 + i.to_s
220
                }.join( "| \\\n" ) + " \\\n" +
221
                t + $tab + '"' + "\n"
222
            
223
            t + "#{@name} [\n" +
224
            @options.to_a.collect{ |i|
225
                i[1] && i[0] != 'label' ? 
226
                    t + $tab + "#{i[0]} = #{i[1]}" : nil
227
            }.compact.join( ",\n" ) + ( label != '' ? ",\n" : "\n" ) + 
228
            label +
229
            t + "]\n" 
230
      end
212
            label = @options['shape'] != 'record' && @ports.length == 0 ?
213
                    @options['label'] ?
214
                        t + $tab + "label = \"#{@options['label']}\"\n" :
215
                        '' :
216
                    t + $tab + 'label = "' + " \\\n" +
217
                    t + $tab2 + "#{@options['label']}| \\\n" +
218
                    @ports.collect{ |i|
219
                        t + $tab2 + i.to_s
220
                    }.join( "| \\\n" ) + " \\\n" +
221
                    t + $tab + '"' + "\n"
231 222

  
232
  end # class DOTNode
223
                t + "#{@name} [\n" +
224
                @options.to_a.collect{ |i|
225
                    i[1] && i[0] != 'label' ?
226
                        t + $tab + "#{i[0]} = #{i[1]}" : nil
227
                }.compact.join( ",\n" ) + ( label != '' ? ",\n" : "\n" ) +
228
                label +
229
                t + "]\n"
230
        end
233 231

  
234
  # A subgraph element is the same to graph, but has another header in dot
235
  # notation.
232
    end # class DOTNode
236 233

  
237
  class DOTSubgraph < DOTElement
234
    # A subgraph element is the same to graph, but has another header in dot
235
    # notation.
238 236

  
239
    @nodes
240
    @dot_string
237
    class DOTSubgraph < DOTElement
241 238

  
242
    def initialize (params = {}, option_list = GRAPH_OPTS)
243
      super(params, option_list)
244
      @nodes      = params['nodes'] ? params['nodes'] : []
245
      @dot_string = 'graph'
246
    end
239
        @nodes
240
        @dot_string
247 241

  
248
    def each_node
249
      @nodes.each{ |i| yield i }
250
    end
242
        def initialize (params = {}, option_list = GRAPH_OPTS)
243
            super(params, option_list)
244
            @nodes      = params['nodes'] ? params['nodes'] : []
245
            @dot_string = 'graph'
246
        end
251 247

  
252
    def << (thing)
253
      @nodes << thing
254
    end
255
       
256
    def push (thing)
257
      @nodes.push( thing )
258
    end
248
        def each_node
249
            @nodes.each{ |i| yield i }
250
        end
259 251

  
260
    def pop
261
      @nodes.pop
262
    end
252
        def << (thing)
253
            @nodes << thing
254
        end
263 255

  
264
    def to_s (t = '')
265
      hdr = t + "#{@dot_string} #{@name} {\n"
256
        def push (thing)
257
            @nodes.push( thing )
258
        end
266 259

  
267
      options = @options.to_a.collect{ |name, val|
268
        val && name != 'label' ? 
269
          t + $tab + "#{name} = #{val}" : 
270
          name ? t + $tab + "#{name} = \"#{val}\"" : nil
271
      }.compact.join( "\n" ) + "\n"
260
        def pop
261
            @nodes.pop
262
        end
272 263

  
273
      nodes = @nodes.collect{ |i|
274
        i.to_s( t + $tab )
275
      }.join( "\n" ) + "\n" 
276
      hdr + options + nodes + t + "}\n"
277
    end
264
        def to_s (t = '')
265
            hdr = t + "#{@dot_string} #{@name} {\n"
278 266

  
279
  end # class DOTSubgraph
267
            options = @options.to_a.collect{ |name, val|
268
                val && name != 'label' ?
269
                    t + $tab + "#{name} = #{val}" :
270
                    name ? t + $tab + "#{name} = \"#{val}\"" : nil
271
            }.compact.join( "\n" ) + "\n"
280 272

  
281
  # This is a graph.
273
            nodes = @nodes.collect{ |i|
274
                i.to_s( t + $tab )
275
            }.join( "\n" ) + "\n"
276
            hdr + options + nodes + t + "}\n"
277
        end
282 278

  
283
  class DOTDigraph < DOTSubgraph
279
    end # class DOTSubgraph
280

  
281
    # This is a graph.
282

  
283
    class DOTDigraph < DOTSubgraph
284 284

  
285 285
    def initialize (params = {}, option_list = GRAPH_OPTS)
286
      super(params, option_list)
287
      @dot_string = 'digraph'
286
        super(params, option_list)
287
        @dot_string = 'digraph'
288 288
    end
289 289

  
290
  end # class DOTDigraph
290
    end # class DOTDigraph
291 291

  
292
  # This is an edge.
292
    # This is an edge.
293 293

  
294
  class DOTEdge < DOTElement
294
    class DOTEdge < DOTElement
295 295

  
296
    attr_accessor :from, :to
296
        attr_accessor :from, :to
297 297

  
298
    def initialize (params = {}, option_list = EDGE_OPTS)
299
      super(params, option_list)
300
      @from = params['from'] ? params['from'] : nil
301
      @to   = params['to'] ? params['to'] : nil
302
    end
298
        def initialize (params = {}, option_list = EDGE_OPTS)
299
            super(params, option_list)
300
            @from = params['from'] ? params['from'] : nil
301
            @to   = params['to'] ? params['to'] : nil
302
        end
303 303
       
304
    def edge_link
305
      '--'
306
    end
307

  
308
    def to_s (t = '')
309
      t + "#{@from} #{edge_link} #{to} [\n" +
310
          @options.to_a.collect{ |i|
311
            i[1] && i[0] != 'label' ? 
312
              t + $tab + "#{i[0]} = #{i[1]}" : 
313
              i[1] ? t + $tab + "#{i[0]} = \"#{i[1]}\"" : nil
314
          }.compact.join( "\n" ) + "\n" + t + "]\n"
315
    end
316

  
317
  end # class DOTEdge
304
        def edge_link
305
            '--'
306
        end
307

  
308
        def to_s (t = '')
309
            t + "#{@from} #{edge_link} #{to} [\n" +
310
                @options.to_a.collect{ |i|
311
                    i[1] && i[0] != 'label' ?
312
                        t + $tab + "#{i[0]} = #{i[1]}" :
313
                        i[1] ? t + $tab + "#{i[0]} = \"#{i[1]}\"" : nil
314
                }.compact.join( "\n" ) + "\n" + t + "]\n"
315
        end
316

  
317
    end # class DOTEdge
318 318
          
319
  class DOTDirectedEdge < DOTEdge
319
    class DOTDirectedEdge < DOTEdge
320 320

  
321
    def edge_link
322
      '->'
323
    end
321
        def edge_link
322
            '->'
323
        end
324 324

  
325
  end                           # class DOTDirectedEdge
326
end                             # module DOT
325
    end # class DOTDirectedEdge
326
end # module DOT
b/lib/puppet/external/event-loop/better-definers.rb
18 18
# Boston, MA 02110-1301, USA.
19 19

  
20 20
class Symbol
21
  def predicate?
22
    to_s.include? "?" end
23
  def imperative?
24
    to_s.include? "!" end
25
  def writer?
26
    to_s.include? "=" end
27

  
28
  def punctuated?
29
    predicate? or imperative? or writer? end
30
  def without_punctuation
31
    to_s.delete("?!=").to_sym end
32

  
33
  def predicate
34
    without_punctuation.to_s + "?" end
35
  def imperative
36
    without_punctuation.to_s + "!" end
37
  def writer
38
    without_punctuation.to_s + "=" end
21
    def predicate?
22
        to_s.include? "?" end
23
    def imperative?
24
        to_s.include? "!" end
25
    def writer?
26
        to_s.include? "=" end
27

  
28
    def punctuated?
29
        predicate? or imperative? or writer? end
30
    def without_punctuation
31
        to_s.delete("?!=").to_sym end
32

  
33
    def predicate
34
        without_punctuation.to_s + "?" end
35
    def imperative
36
        without_punctuation.to_s + "!" end
37
    def writer
38
        without_punctuation.to_s + "=" end
39 39
end
40 40

  
41 41
class Hash
42
  def collect! (&block)
43
    replace Hash[*collect(&block).flatten]
44
  end
42
    def collect! (&block)
43
        replace Hash[*collect(&block).flatten]
44
    end
45 45

  
46
  def flatten
47
    to_a.flatten
48
  end
46
    def flatten
47
        to_a.flatten
48
    end
49 49
end
50 50

  
51 51
module Kernel
52
  def returning (value)
53
    yield value ; value
54
  end
52
    def returning (value)
53
        yield value ; value
54
    end
55 55
end
56 56

  
57 57
class Module
58
  def define_hard_aliases (name_pairs)
59
    for new_aliases, existing_name in name_pairs do
60
      new_aliases.kind_of? Array or new_aliases = [new_aliases]
61
      for new_alias in new_aliases do
62
        alias_method(new_alias, existing_name)
63
      end
58
    def define_hard_aliases (name_pairs)
59
        for new_aliases, existing_name in name_pairs do
60
            new_aliases.kind_of? Array or new_aliases = [new_aliases]
61
            for new_alias in new_aliases do
62
                alias_method(new_alias, existing_name)
63
            end
64
        end
64 65
    end
65
  end
66

  
67
  def define_soft_aliases (name_pairs)
68
    for new_aliases, existing_name in name_pairs do
69
      new_aliases.kind_of? Array or new_aliases = [new_aliases]
70
      for new_alias in new_aliases do
71
        class_eval %{def #{new_alias}(*args, &block)
72
                       #{existing_name}(*args, &block) end}
73
      end
66

  
67
    def define_soft_aliases (name_pairs)
68
        for new_aliases, existing_name in name_pairs do
69
            new_aliases.kind_of? Array or new_aliases = [new_aliases]
70
            for new_alias in new_aliases do
71
                class_eval %{def #{new_alias}(*args, &block)
72
                            #{existing_name}(*args, &block) end}
73
            end
74
        end
74 75
    end
75
  end
76

  
77
  define_soft_aliases \
78
    :define_hard_alias => :define_hard_aliases,
79
    :define_soft_alias => :define_soft_aliases
80

  
81
  # This method lets you define predicates like :foo?,
82
  # which will be defined to return the value of @foo.
83
  def define_readers (*names)
84
    for name in names.map { |x| x.to_sym } do
85
      if name.punctuated?
86
        # There's no way to define an efficient reader whose
87
        # name is different from the instance variable.
88
        class_eval %{def #{name} ; @#{name.without_punctuation} end}
89
      else
90
        # Use `attr_reader' to define an efficient method.
91
        attr_reader(name)
92
      end
76

  
77
    define_soft_aliases \
78
        :define_hard_alias => :define_hard_aliases,
79
        :define_soft_alias => :define_soft_aliases
80

  
81
    # This method lets you define predicates like :foo?,
82
    # which will be defined to return the value of @foo.
83
    def define_readers (*names)
84
        for name in names.map { |x| x.to_sym } do
85
            if name.punctuated?
86
                # There's no way to define an efficient reader whose
87
                # name is different from the instance variable.
88
                class_eval %{def #{name} ; @#{name.without_punctuation} end}
89
            else
90
                # Use `attr_reader' to define an efficient method.
91
                attr_reader(name)
92
            end
93
        end
93 94
    end
94
  end
95

  
96
  def writer_defined? (name)
97
    method_defined? name.to_sym.writer
98
  end
99

  
100
  # If you pass a predicate symbol :foo? to this method, it'll first
101
  # define a regular writer method :foo, without a question mark.
102
  # Then it'll define an imperative writer method :foo! as a shorthand
103
  # for setting the property to true.
104
  def define_writers (*names, &body)
105
    for name in names.map { |x| x.to_sym } do
106
      if block_given?
107
        define_method(name.writer, &body)
108
      else
109
        attr_writer(name.without_punctuation)
110
      end
111
      if name.predicate?
112
        class_eval %{def #{name.imperative}
113
                       self.#{name.writer} true end}
114
      end
95

  
96
    def writer_defined? (name)
97
        method_defined? name.to_sym.writer
115 98
    end
116
  end
117 99

  
118
  define_soft_aliases \
119
    :define_reader => :define_readers,
120
    :define_writer => :define_writers
100
    # If you pass a predicate symbol :foo? to this method, it'll first
101
    # define a regular writer method :foo, without a question mark.
102
    # Then it'll define an imperative writer method :foo! as a shorthand
103
    # for setting the property to true.
104
    def define_writers (*names, &body)
105
        for name in names.map { |x| x.to_sym } do
106
            if block_given?
107
                define_method(name.writer, &body)
108
            else
109
                attr_writer(name.without_punctuation)
110
            end
111
            if name.predicate?
112
                class_eval %{def #{name.imperative}
113
                           self.#{name.writer} true end}
114
            end
115
        end
116
    end
121 117

  
122
  # We don't need a singular alias for `define_accessors',
123
  # because it always defines at least two methods.
118
    define_soft_aliases \
119
        :define_reader => :define_readers,
120
        :define_writer => :define_writers
124 121

  
125
  def define_accessors (*names)
126
    define_readers(*names)
127
    define_writers(*names)
128
  end
122
    # We don't need a singular alias for `define_accessors',
123
    # because it always defines at least two methods.
129 124

  
130
  def define_opposite_readers (name_pairs)
131
    name_pairs.collect! { |k, v| [k.to_sym, v.to_sym] }
132
    for opposite_name, name in name_pairs do
133
      define_reader(name) unless method_defined? name
134
      class_eval %{def #{opposite_name} ; not #{name} end}
125
    def define_accessors (*names)
126
        define_readers(*names)
127
        define_writers(*names)
135 128
    end
136
  end
137

  
138
  def define_opposite_writers (name_pairs)
139
    name_pairs.collect! { |k, v| [k.to_sym, v.to_sym] }
140
    for opposite_name, name in name_pairs do
141
      define_writer(name) unless writer_defined? name
142
      class_eval %{def #{opposite_name.writer} x
143
                     self.#{name.writer} !x end} 
144
      class_eval %{def #{opposite_name.imperative}
145
                     self.#{name.writer} false end}
129

  
130
    def define_opposite_readers (name_pairs)
131
        name_pairs.collect! { |k, v| [k.to_sym, v.to_sym] }
132
        for opposite_name, name in name_pairs do
133
            define_reader(name) unless method_defined? name
134
            class_eval %{def #{opposite_name} ; not #{name} end}
135
        end
146 136
    end
147
  end
148 137

  
149
  define_soft_aliases \
150
    :define_opposite_reader => :define_opposite_readers,
151
    :define_opposite_writer => :define_opposite_writers
138
    def define_opposite_writers (name_pairs)
139
        name_pairs.collect! { |k, v| [k.to_sym, v.to_sym] }
140
        for opposite_name, name in name_pairs do
141
            define_writer(name) unless writer_defined? name
142
            class_eval %{def #{opposite_name.writer} x
143
                         self.#{name.writer} !x end}
144
            class_eval %{def #{opposite_name.imperative}
145
                         self.#{name.writer} false end}
146
        end
147
    end
148

  
149
    define_soft_aliases \
150
        :define_opposite_reader => :define_opposite_readers,
151
        :define_opposite_writer => :define_opposite_writers
152 152

  
153
  def define_opposite_accessors (name_pairs)
154
    define_opposite_readers name_pairs
155
    define_opposite_writers name_pairs
156
  end
153
    def define_opposite_accessors (name_pairs)
154
        define_opposite_readers name_pairs
155
        define_opposite_writers name_pairs
156
    end
157 157

  
158
  def define_reader_with_opposite (name_pair, &body)
159
    name, opposite_name = name_pair.flatten.collect { |x| x.to_sym }
160
    define_method(name, &body)
161
    define_opposite_reader(opposite_name => name)
162
  end
158
    def define_reader_with_opposite (name_pair, &body)
159
        name, opposite_name = name_pair.flatten.collect { |x| x.to_sym }
160
        define_method(name, &body)
161
        define_opposite_reader(opposite_name => name)
162
    end
163 163

  
164
  def define_writer_with_opposite (name_pair, &body)
165
    name, opposite_name = name_pair.flatten.collect { |x| x.to_sym }
166
    define_writer(name, &body)
167
    define_opposite_writer(opposite_name => name)
168
  end
164
    def define_writer_with_opposite (name_pair, &body)
165
        name, opposite_name = name_pair.flatten.collect { |x| x.to_sym }
166
        define_writer(name, &body)
167
        define_opposite_writer(opposite_name => name)
168
    end
169 169

  
170 170
  public :define_method
171 171

  
172
  def define_methods (*names, &body)
173
    names.each { |name| define_method(name, &body) }
174
  end
172
    def define_methods (*names, &body)
173
        names.each { |name| define_method(name, &body) }
174
    end
175 175
  
176
  def define_private_methods (*names, &body)
177
    define_methods(*names, &body)
178
    names.each { |name| private name }
179
  end
180

  
181
  def define_protected_methods (*names, &body)
182
    define_methods(*names, &body)
183
    names.each { |name| protected name }
184
  end
185

  
186
  def define_private_method (name, &body)
187
    define_method(name, &body)
188
    private name
189
  end
190

  
191
  def define_protected_method (name, &body)
192
    define_method(name, &body)
193
    protected name
194
  end
176
    def define_private_methods (*names, &body)
177
        define_methods(*names, &body)
178
        names.each { |name| private name }
179
    end
180

  
181
    def define_protected_methods (*names, &body)
182
        define_methods(*names, &body)
183
        names.each { |name| protected name }
184
    end
185

  
186
    def define_private_method (name, &body)
187
        define_method(name, &body)
188
        private name
189
    end
190

  
191
    def define_protected_method (name, &body)
192
        define_method(name, &body)
193
        protected name
194
    end
195 195
end
196 196

  
197 197
class ImmutableAttributeError < StandardError
198
  def initialize (attribute=nil, message=nil)
199
    super message
200
    @attribute = attribute
201
  end
202

  
203
  define_accessors :attribute
204

  
205
  def to_s
206
    if @attribute and @message
207
      "cannot change the value of `#@attribute': #@message"
208
    elsif @attribute
209
      "cannot change the value of `#@attribute'"
210
    elsif @message
211
      "cannot change the value of attribute: #@message"
212
    else
213
      "cannot change the value of attribute"
198
    def initialize (attribute=nil, message=nil)
199
        super message
200
        @attribute = attribute
201
    end
202

  
203
    define_accessors :attribute
204

  
205
    def to_s
206
        if @attribute and @message
207
            "cannot change the value of `#@attribute': #@message"
208
        elsif @attribute
209
            "cannot change the value of `#@attribute'"
210
        elsif @message
211
            "cannot change the value of attribute: #@message"
212
        else
213
            "cannot change the value of attribute"
214
        end
214 215
    end
215
  end
216 216
end
217 217

  
218 218
class Module
219
  # Guard each of the specified attributes by replacing the writer
220
  # method with a proxy that asks the supplied block before proceeding
221
  # with the change.
222
  #
223
  # If it's okay to change the attribute, the block should return
224
  # either nil or the symbol :mutable.  If it isn't okay, the block
225
  # should return a string saying why the attribute can't be changed.
226
  # If you don't want to provide a reason, you can have the block
227
  # return just the symbol :immutable.
228
  def guard_writers(*names, &predicate)
229
    for name in names.map { |x| x.to_sym } do
230
      define_hard_alias("__unguarded_#{name.writer}" => name.writer)
231
      define_method(name.writer) do |new_value|
232
        case result = predicate.call
... This diff was truncated because it exceeds the maximum size that can be displayed.