caesars 0.7.0 → 0.7.1

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/CHANGES.txt CHANGED
@@ -1,6 +1,13 @@
1
1
  CAESARS -- CHANGES
2
2
 
3
3
 
4
+ #### 0.7.1 (2009-06-08) ###############################
5
+
6
+ * FIXED: Updated file manifest in gemspec
7
+ * FIXED: Correct mistake in rdocs for Caesars::Config.new
8
+ * CHANGE: Caesars::** classes moved into separate files.
9
+
10
+
4
11
  #### 0.7.0 (2009-06-03) ###############################
5
12
 
6
13
  * CHANGE: Post-processing for Caesars::Config classes now occurs
data/caesars.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  @spec = Gem::Specification.new do |s|
2
2
  s.name = "caesars"
3
3
  s.rubyforge_project = "caesars"
4
- s.version = "0.7.0"
4
+ s.version = "0.7.1"
5
5
  s.specification_version = 1 if s.respond_to? :specification_version=
6
6
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
7
7
 
@@ -22,6 +22,9 @@
22
22
  bin/party.conf
23
23
  caesars.gemspec
24
24
  lib/caesars.rb
25
+ lib/caesars/config.rb
26
+ lib/caesars/exceptions.rb
27
+ lib/caesars/hash.rb
25
28
  lib/caesars/orderedhash.rb
26
29
  )
27
30
 
data/lib/caesars.rb CHANGED
@@ -8,9 +8,12 @@
8
8
  # See bin/example
9
9
  #
10
10
  class Caesars
11
+
11
12
  require 'caesars/orderedhash'
12
-
13
- VERSION = "0.7.0"
13
+ require 'caesars/exceptions'
14
+ require 'caesars/config'
15
+
16
+ VERSION = "0.7.1"
14
17
  @@debug = false
15
18
  @@chilled = {}
16
19
  @@forced_array = {}
@@ -18,7 +21,9 @@ class Caesars
18
21
  @@known_symbols = []
19
22
  @@known_symbols_by_glass = {}
20
23
  HASH_TYPE = (RUBY_VERSION =~ /1.9/) ? ::Hash : Caesars::OrderedHash
21
-
24
+
25
+ require 'caesars/hash'
26
+
22
27
  def Caesars.enable_debug; @@debug = true; end
23
28
  def Caesars.disable_debug; @@debug = false; end
24
29
  def Caesars.debug?; @@debug; end
@@ -59,52 +64,9 @@ class Caesars
59
64
  @@known_symbols_by_glass[g].member?(s.to_sym)
60
65
  end
61
66
 
62
- # A subclass of ::Hash that provides method names for hash parameters.
63
- # It's like a lightweight OpenStruct.
64
- # ch = Caesars::Hash[:tabasco => :lots!]
65
- # puts ch.tabasco # => lots!
66
- #
67
- class Hash < HASH_TYPE
68
- def method_missing(meth)
69
- self[meth] if self.has_key?(meth)
70
- end
71
-
72
- # Returns a clone of itself and all children cast as ::Hash objects
73
- def to_hash(hash=self)
74
- return hash unless hash.is_a?(Caesars::Hash) # nothing to do
75
- target = (Caesars::HASH_TYPE)[dup]
76
- hash.keys.each do |key|
77
- if hash[key].is_a? Caesars::Hash
78
- target[key] = hash[key].to_hash
79
- next
80
- elsif hash[key].is_a? Array
81
- target[key] = hash[key].collect { |h| to_hash(h) }
82
- next
83
- end
84
- target[key] = hash[key]
85
- end
86
- target
87
- end
88
-
89
- end
90
-
91
67
  # An instance of Caesars::Hash which contains the data specified by your DSL
92
68
  attr_accessor :caesars_properties
93
69
 
94
- class Error < RuntimeError
95
- attr_accessor :backtrace
96
- def initialize(obj=nil); @obj = obj; end
97
- def message; "#{self.class}: #{@obj}"; end
98
- end
99
- class SyntaxError < Caesars::Error
100
- def message
101
- msg = "Syntax error in #{@obj}"
102
- bt = @backtrace
103
- msg << " in " << bt.first.scan(/\`(.+?)'/).flatten.first if bt
104
- msg
105
- end
106
- end
107
-
108
70
  def initialize(name=nil)
109
71
  @caesars_name = name if name
110
72
  @caesars_properties = Caesars::Hash.new
@@ -576,191 +538,4 @@ class Caesars
576
538
  end
577
539
 
578
540
 
579
- # A helper for loading a DSL from a config file.
580
- #
581
- # Usage:
582
- #
583
- # class Staff < Caesars; end;
584
- # class StaffConfig < Caesars::Config
585
- # dsl Staff::DSL
586
- # end
587
- # @config = StaffConfig.new(:path => '/path/2/staff_dsl.rb')
588
- # p @config.staff # => <Staff:0x7ea450 ... >
589
- #
590
- class Caesars::Config
591
- attr_accessor :paths
592
- attr_reader :options
593
- attr_reader :verbose
594
-
595
- @@glasses = []
596
-
597
- # Used by postprocess to tell refresh to reload all configs.
598
- class ForceRefresh < RuntimeError
599
- # The list of config types that need to be refreshed. This is currently
600
- # for informational-purposes only. It does not affect which files/config
601
- # types are refreshed. See Caesars::Config::ForcedRefresh
602
- attr_reader :glasses
603
- def initialize(*glasses); @glasses = glasses; end
604
- def message; "Force refresh of: #{@glasses.join(',')}"; end
605
- end
606
-
607
- # +args+ is a last of config file paths to load into this instance.
608
- # If the last argument is a hash, it's assumed to be a list of
609
- # options. The available options are:
610
- #
611
- # <li>:verbose => true or false</li>
612
- #
613
- def initialize(*args)
614
- # We store the options hash b/c we reapply them when we refresh.
615
- @options = args.last.kind_of?(Hash) ? args.pop : {}
616
- @paths = args.empty? ? [] : args
617
- @options = {}
618
- @forced_refreshes = 0
619
- refresh
620
- end
621
-
622
- def verbose=(enable)
623
- @verbose = enable == true
624
- @options[:verbose] = @verbose
625
- end
626
-
627
- # Reset all config instance variables to nil.
628
- def caesars_init
629
- # Remove instance variables used to populate DSL data
630
- keys.each { |confname| instance_variable_set("@#{confname}", nil) }
631
- # Re-apply options
632
- @options.each_pair do |n,v|
633
- self.send("#{n}=", v) if respond_to?("#{n}=")
634
- end
635
- check_paths # make sure files exist
636
- end
637
-
638
- # This method is a stub. It gets called by refresh after each
639
- # config file has be loaded. You can use it to run file specific
640
- # processing on the configuration before it's used elsewhere.
641
- def postprocess
642
- end
643
-
644
- # Clear all current configuration (sets all config instance
645
- # variables to nil) and reload all config files in +@paths+.
646
- # After each path is loaded, Caesars::Config.postprocess is
647
- # called. If a ForceRefresh exception is raise, refresh is
648
- # run again from the start. This is useful in the case
649
- # where one DSL can affect the parsing of another. Note that
650
- # refresh only clears the instance variables, the class vars
651
- # for each of the DSLs are not affected so all calls to
652
- # +forced_array+, +forced_hash+, +chill+ and +forced_ignore+
653
- # are unaffected.
654
- #
655
- # Rudy has an example of forced refreshing in action. See
656
- # the files (http://github.com/solutious/rudy):
657
- #
658
- # * +lib/rudy/config.rb+
659
- # * +lib/rudy/config/objects.rb+.
660
- #
661
- def refresh
662
- caesars_init # Delete all current configuration
663
- @@glasses.each { |glass| extend glass }
664
-
665
- begin
666
- current_path = nil # used in error messages
667
- @paths.each do |path|
668
- current_path = path
669
- puts "Loading config from #{path}" if @verbose || Caesars.debug?
670
- dsl = File.read path
671
- # eval so the DSL code can be executed in this namespace.
672
- eval dsl, binding, __FILE__, __LINE__
673
- end
674
-
675
- # Execute Caesars::Config.postprocesses after all files are loaded.
676
- postprocess # Can raise ForceRefresh
677
-
678
- rescue Caesars::Config::ForceRefresh => ex
679
- @forced_refreshes += 1
680
- if @forced_refreshes > 3
681
- STDERR.puts "Too many forced refreshes (#{@forced_refreshes})"
682
- exit 9
683
- end
684
- STDERR.puts ex.message if @verbose || Caesars.debug?
685
- refresh
686
-
687
- #rescue Caesars::Error => ex
688
- # STDERR.puts ex.message
689
- # STDERR.puts ex.backtrace if Caesars.debug?
690
- rescue ArgumentError, SyntaxError => ex
691
- newex = Caesars::SyntaxError.new(current_path)
692
- newex.backtrace = ex.backtrace
693
- raise newex
694
- end
695
- end
696
-
697
- # Checks all values of +@paths+, raises an exception for nil
698
- # values and file paths that don't exist.
699
- def check_paths
700
- @paths.each do |path|
701
- raise "You provided a nil value" unless path
702
- raise "Config file #{path} does not exist!" unless File.exists?(path)
703
- end
704
- end
705
-
706
- # Do any of the known DSLs have config data?
707
- def empty?
708
- keys.each do |obj|
709
- return false if self.respond_to?(obj.to_sym)
710
- end
711
- true
712
- end
713
-
714
- # Specify a DSL class (+glass+) to include in this config.
715
- #
716
- # class CoolDrink < Caesars::Config
717
- # dsl CoolDrink::Flavours::DSL
718
- # end
719
- #
720
- def self.dsl(glass)
721
- @@glasses << glass
722
- end
723
-
724
- # Provide a hash-like interface for Config classes.
725
- # +name+ is the name of a DSL config.
726
- #
727
- # class CoolDrink < Caesars::Config
728
- # dsl CoolDrink::Flavours::DSL
729
- # end
730
- #
731
- # cd = CoolDrink.new('/path/2/config')
732
- # cd[:flavours] # => {}
733
- #
734
- def [](name)
735
- self.send(name) if respond_to?(name)
736
- end
737
-
738
- # Returns the list of known DSL config names.
739
- # class CoolDrink < Caesars::Config
740
- # dsl CoolDrink::Flavours::DSL
741
- # end
742
- #
743
- # cd = CoolDrink.new('/path/2/config')
744
- # cd.keys # => [:flavours]
745
- #
746
- def keys
747
- @@glasses.collect { |glass| glass.methname }
748
- end
749
-
750
- # Is +name+ a known configuration type?
751
- #
752
- # class CoolDrink < Caesars::Config
753
- # dsl CoolDrink::Flavours::DSL
754
- # end
755
- #
756
- # cd = CoolDrink.new('/path/2/config')
757
- # cd.has_key?(:taste) # => false
758
- # cd.has_key?(:flavours) # => true
759
- #
760
- def has_key?(name)
761
- respond_to?(name)
762
- end
763
- end
764
-
765
-
766
541
 
@@ -0,0 +1,190 @@
1
+
2
+ # A helper for loading a DSL from a config file.
3
+ #
4
+ # Usage:
5
+ #
6
+ # class Staff < Caesars; end;
7
+ # class StaffConfig < Caesars::Config
8
+ # dsl Staff::DSL
9
+ # end
10
+ # @config = StaffConfig.new('/path/2/staff_dsl.rb')
11
+ # p @config.staff # => <Staff:0x7ea450 ... >
12
+ #
13
+ class Caesars
14
+ class Config
15
+ attr_accessor :paths
16
+ attr_reader :options
17
+ attr_reader :verbose
18
+
19
+ @@glasses = []
20
+
21
+ # Used by postprocess to tell refresh to reload all configs.
22
+ class ForceRefresh < RuntimeError
23
+ # The list of config types that need to be refreshed. This is currently
24
+ # for informational-purposes only. It does not affect which files/config
25
+ # types are refreshed. See Caesars::Config::ForcedRefresh
26
+ attr_reader :glasses
27
+ def initialize(*glasses); @glasses = glasses; end
28
+ def message; "Force refresh of: #{@glasses.join(',')}"; end
29
+ end
30
+
31
+ # +args+ is a last of config file paths to load into this instance.
32
+ # If the last argument is a hash, it's assumed to be a list of
33
+ # options. The available options are:
34
+ #
35
+ # <li>:verbose => true or false</li>
36
+ #
37
+ def initialize(*args)
38
+ # We store the options hash b/c we reapply them when we refresh.
39
+ @options = args.last.kind_of?(Hash) ? args.pop : {}
40
+ @paths = args.empty? ? [] : args
41
+ @options = {}
42
+ @forced_refreshes = 0
43
+ refresh
44
+ end
45
+
46
+ def verbose=(enable)
47
+ @verbose = enable == true
48
+ @options[:verbose] = @verbose
49
+ end
50
+
51
+ # Reset all config instance variables to nil.
52
+ def caesars_init
53
+ # Remove instance variables used to populate DSL data
54
+ keys.each { |confname| instance_variable_set("@#{confname}", nil) }
55
+ # Re-apply options
56
+ @options.each_pair do |n,v|
57
+ self.send("#{n}=", v) if respond_to?("#{n}=")
58
+ end
59
+ check_paths # make sure files exist
60
+ end
61
+
62
+ # This method is a stub. It gets called by refresh after each
63
+ # config file has be loaded. You can use it to run file specific
64
+ # processing on the configuration before it's used elsewhere.
65
+ def postprocess
66
+ end
67
+
68
+ # Clear all current configuration (sets all config instance
69
+ # variables to nil) and reload all config files in +@paths+.
70
+ # After each path is loaded, Caesars::Config.postprocess is
71
+ # called. If a ForceRefresh exception is raise, refresh is
72
+ # run again from the start. This is useful in the case
73
+ # where one DSL can affect the parsing of another. Note that
74
+ # refresh only clears the instance variables, the class vars
75
+ # for each of the DSLs are not affected so all calls to
76
+ # +forced_array+, +forced_hash+, +chill+ and +forced_ignore+
77
+ # are unaffected.
78
+ #
79
+ # Rudy has an example of forced refreshing in action. See
80
+ # the files (http://github.com/solutious/rudy):
81
+ #
82
+ # * +lib/rudy/config.rb+
83
+ # * +lib/rudy/config/objects.rb+.
84
+ #
85
+ def refresh
86
+ caesars_init # Delete all current configuration
87
+ @@glasses.each { |glass| extend glass }
88
+
89
+ begin
90
+ current_path = nil # used in error messages
91
+ @paths.each do |path|
92
+ current_path = path
93
+ puts "Loading config from #{path}" if @verbose || Caesars.debug?
94
+ dsl = File.read path
95
+ # eval so the DSL code can be executed in this namespace.
96
+ eval dsl, binding, __FILE__, __LINE__
97
+ end
98
+
99
+ # Execute Caesars::Config.postprocesses after all files are loaded.
100
+ postprocess # Can raise ForceRefresh
101
+
102
+ rescue Caesars::Config::ForceRefresh => ex
103
+ @forced_refreshes += 1
104
+ if @forced_refreshes > 3
105
+ STDERR.puts "Too many forced refreshes (#{@forced_refreshes})"
106
+ exit 9
107
+ end
108
+ STDERR.puts ex.message if @verbose || Caesars.debug?
109
+ refresh
110
+
111
+ #rescue Caesars::Error => ex
112
+ # STDERR.puts ex.message
113
+ # STDERR.puts ex.backtrace if Caesars.debug?
114
+ rescue ArgumentError, SyntaxError => ex
115
+ newex = Caesars::SyntaxError.new(current_path)
116
+ newex.backtrace = ex.backtrace
117
+ raise newex
118
+ end
119
+ end
120
+
121
+ # Checks all values of +@paths+, raises an exception for nil
122
+ # values and file paths that don't exist.
123
+ def check_paths
124
+ @paths.each do |path|
125
+ raise "You provided a nil value" unless path
126
+ raise "Config file #{path} does not exist!" unless File.exists?(path)
127
+ end
128
+ end
129
+
130
+ # Do any of the known DSLs have config data?
131
+ def empty?
132
+ keys.each do |obj|
133
+ return false if self.respond_to?(obj.to_sym)
134
+ end
135
+ true
136
+ end
137
+
138
+ # Specify a DSL class (+glass+) to include in this config.
139
+ #
140
+ # class CoolDrink < Caesars::Config
141
+ # dsl CoolDrink::Flavours::DSL
142
+ # end
143
+ #
144
+ def self.dsl(glass)
145
+ @@glasses << glass
146
+ end
147
+
148
+ # Provide a hash-like interface for Config classes.
149
+ # +name+ is the name of a DSL config.
150
+ #
151
+ # class CoolDrink < Caesars::Config
152
+ # dsl CoolDrink::Flavours::DSL
153
+ # end
154
+ #
155
+ # cd = CoolDrink.new('/path/2/config')
156
+ # cd[:flavours] # => {}
157
+ #
158
+ def [](name)
159
+ self.send(name) if respond_to?(name)
160
+ end
161
+
162
+ # Returns the list of known DSL config names.
163
+ # class CoolDrink < Caesars::Config
164
+ # dsl CoolDrink::Flavours::DSL
165
+ # end
166
+ #
167
+ # cd = CoolDrink.new('/path/2/config')
168
+ # cd.keys # => [:flavours]
169
+ #
170
+ def keys
171
+ @@glasses.collect { |glass| glass.methname }
172
+ end
173
+
174
+ # Is +name+ a known configuration type?
175
+ #
176
+ # class CoolDrink < Caesars::Config
177
+ # dsl CoolDrink::Flavours::DSL
178
+ # end
179
+ #
180
+ # cd = CoolDrink.new('/path/2/config')
181
+ # cd.has_key?(:taste) # => false
182
+ # cd.has_key?(:flavours) # => true
183
+ #
184
+ def has_key?(name)
185
+ respond_to?(name)
186
+ end
187
+
188
+ end
189
+ end
190
+
@@ -0,0 +1,17 @@
1
+
2
+
3
+ class Caesars
4
+ class Error < RuntimeError
5
+ attr_accessor :backtrace
6
+ def initialize(obj=nil); @obj = obj; end
7
+ def message; "#{self.class}: #{@obj}"; end
8
+ end
9
+ class SyntaxError < Caesars::Error
10
+ def message
11
+ msg = "Syntax error in #{@obj}"
12
+ bt = @backtrace
13
+ msg << " in " << bt.first.scan(/\`(.+?)'/).flatten.first if bt
14
+ msg
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+
2
+ # A subclass of ::Hash that provides method names for hash parameters.
3
+ # It's like a lightweight OpenStruct.
4
+ # ch = Caesars::Hash[:tabasco => :lots!]
5
+ # puts ch.tabasco # => lots!
6
+ #
7
+ class Caesars
8
+ class Hash < HASH_TYPE
9
+ def method_missing(meth)
10
+ self[meth] if self.has_key?(meth)
11
+ end
12
+
13
+ # Returns a clone of itself and all children cast as ::Hash objects
14
+ def to_hash(hash=self)
15
+ return hash unless hash.is_a?(Caesars::Hash) # nothing to do
16
+ target = (Caesars::HASH_TYPE)[dup]
17
+ hash.keys.each do |key|
18
+ if hash[key].is_a? Caesars::Hash
19
+ target[key] = hash[key].to_hash
20
+ next
21
+ elsif hash[key].is_a? Array
22
+ target[key] = hash[key].collect { |h| to_hash(h) }
23
+ next
24
+ end
25
+ target[key] = hash[key]
26
+ end
27
+ target
28
+ end
29
+
30
+ end
31
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: caesars
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-03 00:00:00 -04:00
12
+ date: 2009-06-08 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -33,6 +33,9 @@ files:
33
33
  - bin/party.conf
34
34
  - caesars.gemspec
35
35
  - lib/caesars.rb
36
+ - lib/caesars/config.rb
37
+ - lib/caesars/exceptions.rb
38
+ - lib/caesars/hash.rb
36
39
  - lib/caesars/orderedhash.rb
37
40
  has_rdoc: true
38
41
  homepage: http://github.com/delano/caesars