treequel 1.0.1 → 1.0.4

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.
Files changed (73) hide show
  1. data/ChangeLog +176 -14
  2. data/LICENSE +1 -1
  3. data/Rakefile +61 -45
  4. data/Rakefile.local +20 -0
  5. data/bin/treequel +502 -269
  6. data/examples/ldap-rack-auth.rb +2 -0
  7. data/lib/treequel.rb +221 -18
  8. data/lib/treequel/branch.rb +410 -201
  9. data/lib/treequel/branchcollection.rb +25 -13
  10. data/lib/treequel/branchset.rb +42 -40
  11. data/lib/treequel/constants.rb +233 -3
  12. data/lib/treequel/control.rb +95 -0
  13. data/lib/treequel/controls/contentsync.rb +138 -0
  14. data/lib/treequel/controls/pagedresults.rb +162 -0
  15. data/lib/treequel/controls/sortedresults.rb +216 -0
  16. data/lib/treequel/directory.rb +212 -65
  17. data/lib/treequel/exceptions.rb +11 -12
  18. data/lib/treequel/filter.rb +1 -12
  19. data/lib/treequel/mixins.rb +83 -47
  20. data/lib/treequel/monkeypatches.rb +29 -0
  21. data/lib/treequel/schema.rb +23 -19
  22. data/lib/treequel/schema/attributetype.rb +33 -3
  23. data/lib/treequel/schema/ldapsyntax.rb +0 -11
  24. data/lib/treequel/schema/matchingrule.rb +0 -11
  25. data/lib/treequel/schema/matchingruleuse.rb +0 -11
  26. data/lib/treequel/schema/objectclass.rb +36 -10
  27. data/lib/treequel/schema/table.rb +159 -0
  28. data/lib/treequel/sequel_integration.rb +7 -7
  29. data/lib/treequel/utils.rb +4 -66
  30. data/rake/documentation.rb +89 -0
  31. data/rake/helpers.rb +375 -307
  32. data/rake/hg.rb +16 -2
  33. data/rake/manual.rb +11 -6
  34. data/rake/packaging.rb +20 -35
  35. data/rake/publishing.rb +22 -62
  36. data/spec/lib/constants.rb +20 -0
  37. data/spec/lib/control_behavior.rb +44 -0
  38. data/spec/lib/matchers.rb +51 -0
  39. data/spec/treequel/branch_spec.rb +88 -29
  40. data/spec/treequel/branchcollection_spec.rb +24 -1
  41. data/spec/treequel/branchset_spec.rb +123 -51
  42. data/spec/treequel/control_spec.rb +48 -0
  43. data/spec/treequel/controls/contentsync_spec.rb +38 -0
  44. data/spec/treequel/controls/pagedresults_spec.rb +138 -0
  45. data/spec/treequel/controls/sortedresults_spec.rb +171 -0
  46. data/spec/treequel/directory_spec.rb +186 -16
  47. data/spec/treequel/mixins_spec.rb +42 -3
  48. data/spec/treequel/schema/attributetype_spec.rb +22 -20
  49. data/spec/treequel/schema/objectclass_spec.rb +67 -46
  50. data/spec/treequel/schema/table_spec.rb +134 -0
  51. data/spec/treequel_spec.rb +277 -15
  52. metadata +89 -108
  53. data/bin/treequel.orig +0 -963
  54. data/examples/ldap-monitor.rb +0 -143
  55. data/examples/ldap-monitor/public/css/master.css +0 -328
  56. data/examples/ldap-monitor/public/images/card_small.png +0 -0
  57. data/examples/ldap-monitor/public/images/chain_small.png +0 -0
  58. data/examples/ldap-monitor/public/images/globe_small.png +0 -0
  59. data/examples/ldap-monitor/public/images/globe_small_green.png +0 -0
  60. data/examples/ldap-monitor/public/images/plug.png +0 -0
  61. data/examples/ldap-monitor/public/images/shadows/large-30-down.png +0 -0
  62. data/examples/ldap-monitor/public/images/tick.png +0 -0
  63. data/examples/ldap-monitor/public/images/tick_circle.png +0 -0
  64. data/examples/ldap-monitor/public/images/treequel-favicon.png +0 -0
  65. data/examples/ldap-monitor/views/backends.erb +0 -41
  66. data/examples/ldap-monitor/views/connections.erb +0 -74
  67. data/examples/ldap-monitor/views/databases.erb +0 -39
  68. data/examples/ldap-monitor/views/dump_subsystem.erb +0 -14
  69. data/examples/ldap-monitor/views/index.erb +0 -14
  70. data/examples/ldap-monitor/views/layout.erb +0 -35
  71. data/examples/ldap-monitor/views/listeners.erb +0 -30
  72. data/rake/rdoc.rb +0 -30
  73. data/rake/win32.rb +0 -190
@@ -9,17 +9,6 @@ require 'treequel/exceptions'
9
9
 
10
10
 
11
11
  # This is a class for representing matchingRule declarations in a Treequel::Schema.
12
- #
13
- # == Authors
14
- #
15
- # * Michael Granger <ged@FaerieMUD.org>
16
- #
17
- # :include: LICENSE
18
- #
19
- #--
20
- #
21
- # Please see the file LICENSE in the base directory for licensing details.
22
- #
23
12
  class Treequel::Schema::MatchingRule
24
13
  include Treequel::Loggable,
25
14
  Treequel::Constants::Patterns
@@ -9,17 +9,6 @@ require 'treequel/exceptions'
9
9
 
10
10
 
11
11
  # This is a class for representing matchingRuleUse declarations in a Treequel::Schema.
12
- #
13
- # == Authors
14
- #
15
- # * Michael Granger <ged@FaerieMUD.org>
16
- #
17
- # :include: LICENSE
18
- #
19
- #--
20
- #
21
- # Please see the file LICENSE in the base directory for licensing details.
22
- #
23
12
  class Treequel::Schema::MatchingRuleUse
24
13
  include Treequel::Loggable,
25
14
  Treequel::Constants::Patterns
@@ -123,12 +123,6 @@ class Treequel::Schema
123
123
  # The name of the objectClass's superior class (if specified)
124
124
  attr_accessor :sup_name
125
125
 
126
- # The Array of the objectClass's MUST OIDs
127
- attr_reader :must_oids
128
-
129
- # The Array of the objectClass's MAY OIDs
130
- attr_reader :may_oids
131
-
132
126
  # The objectClass's extensions (as a String)
133
127
  attr_accessor :extensions
134
128
 
@@ -139,10 +133,26 @@ class Treequel::Schema
139
133
  end
140
134
 
141
135
 
136
+ ### Return the objectClass's MUST OIDs as Symbols (for symbolic OIDs) or Strings (for
137
+ ### dotted-numeric OIDs).
138
+ ### @param [Boolean] include_sup (true) include MUST OIDs inherited from the
139
+ ### objectClass's SUP, if it has one.
140
+ ### @return [Array<Symbol,String>] the objectClass's MUST OIDs
141
+ def must_oids( include_sup=true )
142
+ oids = @must_oids.dup
143
+
144
+ if include_sup && superclass = self.sup
145
+ oids.unshift( *superclass.must_oids )
146
+ end
147
+
148
+ return oids.flatten
149
+ end
150
+
151
+
142
152
  ### Return Treequel::Schema::AttributeType objects for each of the objectClass's
143
153
  ### MUST attributes.
144
- def must
145
- self.must_oids.collect do |oid|
154
+ def must( include_sup=true )
155
+ self.must_oids( include_sup ).collect do |oid|
146
156
  self.log.warn "No attribute type for OID %p (case bug?)" % [ oid ] unless
147
157
  self.schema.attribute_types.key?( oid )
148
158
  self.schema.attribute_types[oid]
@@ -150,10 +160,26 @@ class Treequel::Schema
150
160
  end
151
161
 
152
162
 
163
+ ### Return the objectClass's MAY OIDs as Symbols (for symbolic OIDs) or Strings (for
164
+ ### dotted-numeric OIDs).
165
+ ### @param [Boolean] include_sup (true) include MAY OIDs inherited from the
166
+ ### objectClass's SUP, if it has one.
167
+ ### @return [Array<Symbol,String>] the objectClass's MAY OIDs
168
+ def may_oids( include_sup=true )
169
+ oids = @may_oids.dup
170
+
171
+ if include_sup && superclass = self.sup
172
+ oids.unshift( *superclass.may_oids )
173
+ end
174
+
175
+ return oids.flatten
176
+ end
177
+
178
+
153
179
  ### Return Treequel::Schema::AttributeType objects for each of the objectClass's
154
180
  ### MAY attributes.
155
- def may
156
- self.may_oids.collect do |oid|
181
+ def may( include_sup=true )
182
+ self.may_oids( include_sup ).collect do |oid|
157
183
  self.log.warn "No attribute type for OID %p (case bug?)" % [ oid ] unless
158
184
  self.schema.attribute_types.key?( oid )
159
185
  self.schema.attribute_types[oid]
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'forwardable'
4
+ require 'ldap'
5
+ require 'ldap/schema'
6
+
7
+ require 'treequel'
8
+ require 'treequel/constants'
9
+ require 'treequel/mixins'
10
+
11
+
12
+ # This is an object that is used to store LDAP schema information in a
13
+ # case-insensitive table.
14
+ #
15
+ # == Authors
16
+ #
17
+ # * Michael Granger <ged@FaerieMUD.org>
18
+ # * Mahlon E. Smith <mahlon@martini.nu>
19
+ #
20
+ # :include: LICENSE
21
+ #
22
+ #--
23
+ #
24
+ # Please see the file LICENSE in the base directory for licensing details.
25
+ #
26
+ class Treequel::Schema::Table
27
+ extend Forwardable
28
+ include Treequel::Loggable,
29
+ Treequel::Normalization,
30
+ Treequel::Constants::Patterns
31
+
32
+ # The list of methods that should be delegated through the key-normalization
33
+ # method.
34
+ KEYED_METHODS = [ :"[]", :"[]=", :delete, :fetch, :key?, :has_key?, :include?,
35
+ :member?, :store ]
36
+
37
+
38
+ ### Auto-generate methods which call the given +delegate+ after normalizing
39
+ ### their first argument via +normalize_key+
40
+ def self::def_normalized_delegators( delegate, *syms )
41
+ syms.each do |methodname|
42
+ define_method( methodname ) do |key, *args|
43
+ nkey = normalize_key( key )
44
+ instance_variable_get( delegate ).
45
+ __send__( methodname, nkey, *args )
46
+ end
47
+ end
48
+ end
49
+
50
+
51
+ ### Create a new Treequel::Table using the given +hash+ for initial
52
+ ### values.
53
+ def initialize( initial_values={} )
54
+ @hash = {}
55
+ initial_values.each {|k,v| self.append(k => v) }
56
+ end
57
+
58
+
59
+ ### Make sure +@hash+ is unique on Table duplications.
60
+ def initialize_copy( orig_table ) # :nodoc:
61
+ @hash = orig_table.to_hash
62
+ end
63
+
64
+
65
+ ######
66
+ public
67
+ ######
68
+
69
+ # Delegate a handful of methods to the underlying Hash after normalizing
70
+ # the key.
71
+ def_normalized_delegators :@hash, *KEYED_METHODS
72
+
73
+
74
+ # Delegate some methods to the underlying Hash
75
+ begin
76
+ unoverridden_methods = Hash.instance_methods(false).collect {|mname| mname.to_sym }
77
+ def_delegators :@hash, *( unoverridden_methods - KEYED_METHODS )
78
+ end
79
+
80
+
81
+ ### Return the Table in LDIF format
82
+ def to_s
83
+ @hash.collect do |oid,value|
84
+ "%s: %s" % [ oid, value ]
85
+ end.flatten.sort.join( "\r\n" ) + "\r\n"
86
+ end
87
+
88
+
89
+ ### Return the Table as a hash.
90
+ def to_h
91
+ @hash.dup
92
+ end
93
+ alias_method :to_hash, :to_h
94
+
95
+
96
+ ### Merge +other_table+ into the receiver.
97
+ def merge!( other_table, &merge_callback )
98
+ nhash = normalize_hash( other_table.to_hash )
99
+ @hash.merge!( nhash, &merge_callback )
100
+ end
101
+ alias_method :update!, :merge!
102
+
103
+
104
+ ### Return a new table which is the result of merging the receiver
105
+ ### with +other_table+ in the same fashion as Hash#merge. If the optional
106
+ ### +merge_callback+ block is provided, it is called whenever there is a
107
+ ### key collision between the two.
108
+ def merge( other_table, &merge_callback ) # :yields: key, original_value, new_value
109
+ other = self.dup
110
+ other.merge!( other_table, &merge_callback )
111
+ return other
112
+ end
113
+ alias_method :update, :merge
114
+
115
+
116
+ ### Return an array containing the values associated with the given
117
+ ### keys.
118
+ def values_at( *keys )
119
+ @hash.values_at( *(keys.collect {|k| normalize_key(k)}) )
120
+ end
121
+
122
+
123
+ #########
124
+ protected
125
+ #########
126
+
127
+ ### Proxy method: handle getting/setting headers via methods instead of the
128
+ ### index operator.
129
+ def method_missing( sym, *args )
130
+ # work magic
131
+ return super unless sym.to_s =~ /^([a-z]\w+)(=)?$/
132
+
133
+ # If it's an assignment, the (=)? will have matched
134
+ key, assignment = $1, $2
135
+
136
+ method_body = nil
137
+ if assignment
138
+ method_body = self.make_setter( key )
139
+ else
140
+ method_body = self.make_getter( key )
141
+ end
142
+
143
+ self.class.send( :define_method, sym, &method_body )
144
+ return self.method( sym ).call( *args )
145
+ end
146
+
147
+
148
+ ### Create a Proc that will act as a setter for the given key
149
+ def make_setter( key )
150
+ return Proc.new {|new_value| self[ key ] = new_value }
151
+ end
152
+
153
+
154
+ ### Create a Proc that will act as a getter for the given key
155
+ def make_getter( key )
156
+ return Proc.new { self[key] }
157
+ end
158
+
159
+ end # class Treequel::Schema::Table
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'treequel'
3
+ require 'treequel'
4
4
  require 'treequel/filter'
5
5
 
6
6
  begin
@@ -9,15 +9,15 @@ rescue LoadError => err
9
9
  Treequel.logger.info "Sequel library didn't load: %s: %s" % [ err.class.name, err.message ]
10
10
  Treequel.logger.debug " " + err.backtrace.join( "\n " )
11
11
  end
12
-
13
12
 
14
- # Provide a dummy Sequel::SQL::Expression class for when the Sequel library
15
- # isn't installed.
16
- unless defined?( Sequel ) &&
17
- Sequel.const_defined?( :SQL ) &&
13
+
14
+ unless defined?( Sequel ) &&
15
+ Sequel.const_defined?( :SQL ) &&
18
16
  Sequel::SQL.const_defined?( :Expression )
19
17
 
20
- module Sequel # :nodoc: all
18
+ # Provide a dummy Sequel::SQL::Expression class for when the Sequel library
19
+ # isn't installed.
20
+ module Sequel
21
21
  module SQL
22
22
  class Expression; end
23
23
  end
@@ -9,30 +9,10 @@ require 'treequel'
9
9
  require 'treequel/mixins'
10
10
 
11
11
 
12
- module Treequel # :nodoc:
12
+ module Treequel
13
13
 
14
- #
15
14
  # A alternate formatter for Logger instances.
16
- #
17
- # == Usage
18
- #
19
- # require 'treequel/utils'
20
- # Treequel.logger.formatter = Treequel::LogFormatter.new( Treequel.logger )
21
- #
22
- # == Version
23
- #
24
- # $Id$
25
- #
26
- # == Authors
27
- #
28
- # * Michael Granger <ged@FaerieMUD.org>
29
- #
30
- # :include: LICENSE
31
- #
32
- #--
33
- #
34
- # Please see the file LICENSE in the 'docs' directory for licensing details.
35
- #
15
+ # @private
36
16
  class LogFormatter < Logger::Formatter
37
17
 
38
18
  # The format to output unless debugging is turned on
@@ -87,28 +67,8 @@ module Treequel # :nodoc:
87
67
  end # class LogFormatter
88
68
 
89
69
 
90
- #
91
70
  # A ANSI-colorized formatter for Logger instances.
92
- #
93
- # == Usage
94
- #
95
- # require 'treequel/utils'
96
- # Treequel.logger.formatter = Treequel::ColorLogFormatter.new( Treequel.logger )
97
- #
98
- # == Version
99
- #
100
- # $Id$
101
- #
102
- # == Authors
103
- #
104
- # * Michael Granger <ged@FaerieMUD.org>
105
- #
106
- # :include: LICENSE
107
- #
108
- #--
109
- #
110
- # Please see the file LICENSE in the 'docs' directory for licensing details.
111
- #
71
+ # @private
112
72
  class ColorLogFormatter < Logger::Formatter
113
73
  extend Treequel::ANSIColorUtilities
114
74
 
@@ -160,31 +120,9 @@ module Treequel # :nodoc:
160
120
  end # class LogFormatter
161
121
 
162
122
 
163
-
164
-
165
- #
166
123
  # An alternate formatter for Logger instances that outputs +div+ HTML
167
124
  # fragments.
168
- #
169
- # == Usage
170
- #
171
- # require 'treequel/utils'
172
- # Treequel.logger.formatter = Treequel::HtmlLogFormatter.new( Treequel.logger )
173
- #
174
- # == Version
175
- #
176
- # $Id$
177
- #
178
- # == Authors
179
- #
180
- # * Michael Granger <ged@FaerieMUD.org>
181
- #
182
- # :include: LICENSE
183
- #
184
- #--
185
- #
186
- # Please see the file LICENSE in the 'docs' directory for licensing details.
187
- #
125
+ # @private
188
126
  class HtmlLogFormatter < Logger::Formatter
189
127
  include ERB::Util # for html_escape()
190
128
 
@@ -0,0 +1,89 @@
1
+ #
2
+ # Documentation Rake tasks
3
+ #
4
+
5
+ require 'rake/clean'
6
+
7
+
8
+ # Append docs/lib to the load path if it exists for documentation
9
+ # helpers.
10
+ DOCSLIB = DOCSDIR + 'lib'
11
+ $LOAD_PATH.unshift( DOCSLIB.to_s ) if DOCSLIB.exist?
12
+
13
+ # Make relative string paths of all the stuff we need to generate docs for
14
+ DOCFILES = Rake::FileList[ LIB_FILES + EXT_FILES + GEMSPEC.extra_rdoc_files ]
15
+
16
+ # Documentation coverage constants
17
+ COVERAGE_DIR = BASEDIR + 'coverage'
18
+ COVERAGE_REPORT = COVERAGE_DIR + 'documentation.txt'
19
+
20
+
21
+ # Prefer YARD, fallback to RDoc
22
+ begin
23
+ require 'yard'
24
+ require 'yard/rake/yardoc_task'
25
+
26
+ # Undo the lazy-assed monkeypatch yard/globals.rb installs and
27
+ # re-install them as mixins as they should have been from the
28
+ # start
29
+ # <metamonkeypatch>
30
+ class Object
31
+ remove_method :log
32
+ remove_method :P
33
+ end
34
+
35
+ module YardGlobals
36
+ def P(namespace, name = nil)
37
+ namespace, name = nil, namespace if name.nil?
38
+ YARD::Registry.resolve(namespace, name, false, true)
39
+ end
40
+
41
+ def log
42
+ YARD::Logger.instance
43
+ end
44
+ end
45
+
46
+ class YARD::CLI::Base; include YardGlobals; end
47
+ class YARD::Parser::SourceParser; extend YardGlobals; include YardGlobals; end
48
+ class YARD::Parser::CParser; include YardGlobals; end
49
+ class YARD::CodeObjects::Base; include YardGlobals; end
50
+ class YARD::Handlers::Base; include YardGlobals; end
51
+ class YARD::Handlers::Processor; include YardGlobals; end
52
+ class YARD::Serializers::Base; include YardGlobals; end
53
+ class YARD::RegistryStore; include YardGlobals; end
54
+ class YARD::Docstring; include YardGlobals; end
55
+ module YARD::Templates::Helpers::ModuleHelper; include YardGlobals; end
56
+ # </metamonkeypatch>
57
+
58
+ YARD_OPTIONS = [] unless defined?( YARD_OPTIONS )
59
+
60
+ yardoctask = YARD::Rake::YardocTask.new( :apidocs ) do |task|
61
+ task.files = DOCFILES
62
+ task.options = YARD_OPTIONS
63
+ task.options << '--debug' << '--verbose' if $trace
64
+ end
65
+ yardoctask.before = lambda {
66
+ trace "Calling yardoc like:",
67
+ " yardoc %s" % [ quotelist(yardoctask.options + yardoctask.files).join(' ') ]
68
+ }
69
+
70
+ YARDOC_CACHE = BASEDIR + '.yardoc'
71
+ CLOBBER.include( YARDOC_CACHE.to_s )
72
+
73
+ rescue LoadError
74
+ require 'rdoc/task'
75
+
76
+ desc "Build API documentation in #{API_DOCSDIR}"
77
+ RDoc::Task.new( :apidocs ) do |task|
78
+ task.main = "README"
79
+ task.rdoc_files.include( DOCFILES )
80
+ task.rdoc_dir = API_DOCSDIR.to_s
81
+ task.options = RDOC_OPTIONS
82
+ end
83
+ end
84
+
85
+ # Need the DOCFILES to exist to build the API docs
86
+ task :apidocs => DOCFILES
87
+
88
+ CLEAN.include( API_DOCSDIR.to_s )
89
+