iba 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING.LESSER ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ Copyright (c) 2010--2011 Matijs van Zuijlen
2
+
3
+ Iba is free software; you can redistribute it and/or modify it under the
4
+ terms of the GNU Lesser General Public License as published by the Free Software
5
+ Foundation, either version 3 of the License, or (at your option) any later
6
+ version.
7
+
8
+ This library is distributed in the hope that it will be useful, but WITHOUT
9
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
11
+ more details.
12
+
13
+ You should have received a copy of the GNU Lesser General Public License
14
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+
data/README.rdoc ADDED
@@ -0,0 +1,59 @@
1
+ = Iba
2
+
3
+ by Matijs van Zuijlen
4
+
5
+ == Description
6
+
7
+ Introspective Block Assertions
8
+
9
+ == Features/Problems
10
+
11
+ * Write assertions as a (one-expression) block
12
+ * Assertion message deconstructs the block's expression.
13
+ * Not done yet.
14
+
15
+ == Synopsis
16
+
17
+ # In your test helper:
18
+ require 'iba'
19
+ class Test::Unit::TestCase
20
+ include Iba::BlockAssertion
21
+ end
22
+
23
+ # In your test:
24
+ foo = 24
25
+ assert { foo == 23 } # => "(foo == 23) is false
26
+ # foo is 24."
27
+
28
+ == Details
29
+
30
+ Iba provides an assert method that takes a block. If the block returns
31
+ false, it will try to construct an insightful error message based on the
32
+ contents of the block.
33
+
34
+ Iba's functionality is inspired by Wrong[1], but doesn't use an external
35
+ Ruby parser. This means it will work in contexts where Wrong does not
36
+ (generated code, on the command line). It also means there are more limits
37
+ to the contents of the block.
38
+
39
+ Current limits:
40
+
41
+ * Only single-expression blocks are supported.
42
+ * The expression must start with a method-like identifier (like 'foo', but
43
+ not 'Foo' or '23'). In practice, this produces quite natural results.
44
+
45
+ Iba's implementation is inspired by Arlo[2], a generic combinator library
46
+ for Python.
47
+
48
+ == Install
49
+
50
+ gem install iba
51
+
52
+ == Links
53
+
54
+ [1] https://github.com/sconover/wrong
55
+ [2] http://withoutane.com/rants/2008/12/arlo-generic-combinators-for-python
56
+
57
+ == Licence
58
+
59
+ See the LICENSE file.
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ load 'tasks/setup.rb'
2
+
3
+ task :default => 'test:run'
data/lib/iba.rb ADDED
@@ -0,0 +1,182 @@
1
+ module Iba
2
+
3
+ class Combinator
4
+ def initialize &blk
5
+ @block = blk
6
+ end
7
+
8
+ def call
9
+ @block.call
10
+ end
11
+
12
+ def to_s
13
+ expression._to_s
14
+ end
15
+
16
+ def expression
17
+ @expression ||= EmptyExpression.new._parse(&@block)
18
+ end
19
+
20
+ def analyse
21
+ if expression._to_s == ""
22
+ "empty block"
23
+ else
24
+ str = "#{self.to_s} is #{self.call.inspect}"
25
+ if expression.class == MethodCallExpression and expression._method == :==
26
+ b = @block.binding
27
+ lft = expression._reciever
28
+ rgt = expression._args.first
29
+ exprs = [lft, rgt].map {|e| display_subexpression e}.compact
30
+ str << "\n"
31
+ str << exprs.join(", ")
32
+ end
33
+ str
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def display_subexpression expr
40
+ if expr.class == LiteralExpression
41
+ nil
42
+ else
43
+ str = expr._to_s
44
+ "#{str} is #{eval str, @block.binding}"
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ class EmptyExpression
51
+ def method_missing method, *args
52
+ return MethodCallExpression.new self, method, args
53
+ end
54
+
55
+ def _parse &blk
56
+ b = blk.binding
57
+
58
+ vars = eval "local_variables", b
59
+ vars.each do |v|
60
+ next if v =~ /^_/
61
+ eval "_#{v} = #{v}", b
62
+ eval "#{v} = Iba::MethodCallExpression.new(Iba::EmptyExpression.new, :#{v}, [])", b
63
+ end
64
+
65
+ result = self.instance_eval(&blk)
66
+ unless result.class == MethodCallExpression
67
+ result = LiteralExpression.new(result)
68
+ end
69
+
70
+ vars.each do |v|
71
+ next if v =~ /^_/
72
+ eval "#{v} = _#{v}", b
73
+ end
74
+
75
+ result
76
+ end
77
+
78
+ def _to_s
79
+ ""
80
+ end
81
+ end
82
+
83
+ class LiteralExpression
84
+ def initialize val
85
+ @value = val
86
+ end
87
+
88
+ def _to_s
89
+ @value.to_s
90
+ end
91
+ end
92
+
93
+ class MethodCallExpression
94
+ OPERATORS = [:+]
95
+ def initialize reciever, methodname, args
96
+ @reciever = reciever
97
+ @method = methodname
98
+ @args = args.map {|a| _wrap(a)}
99
+ end
100
+
101
+ def _method
102
+ @method
103
+ end
104
+
105
+ def _reciever
106
+ @reciever
107
+ end
108
+
109
+ def _args
110
+ @args
111
+ end
112
+
113
+ def _to_s
114
+ rcv = @reciever._to_s
115
+ args = @args.map {|a| a.respond_to?(:_to_s) ? a._to_s : a.to_s }
116
+
117
+ if @method == :[]
118
+ "#{rcv}[#{args[0]}]"
119
+ elsif method_is_operator?
120
+ case @args.length
121
+ when 0
122
+ "#{@method.to_s.sub(/@$/, '')}#{rcv}"
123
+ when 1
124
+ "(#{rcv} #{@method} #{args.first})"
125
+ else
126
+ raise NotImplementedError
127
+ end
128
+ else
129
+ str = rcv == "" ? "" : "#{rcv}."
130
+ str << @method.to_s
131
+ unless @args.empty?
132
+ str << "(#{args.join(', ')})"
133
+ end
134
+ str
135
+ end
136
+ end
137
+
138
+ def method_missing method, *args
139
+ super if method.to_s =~ /^_/
140
+ return MethodCallExpression.new self, method, args
141
+ end
142
+
143
+ def method_is_operator?
144
+ @method.to_s !~ /^[a-z]/
145
+ end
146
+
147
+ def to_s
148
+ method_missing :to_s
149
+ end
150
+
151
+ def == other
152
+ method_missing :==, other
153
+ end
154
+
155
+ private
156
+
157
+ def _wrap arg
158
+ if arg.class == MethodCallExpression
159
+ arg
160
+ else
161
+ LiteralExpression.new arg
162
+ end
163
+ end
164
+ end
165
+
166
+ module BlockAssertion
167
+ def assert *args
168
+ if block_given?
169
+ if yield
170
+ assert_block("true") { true }
171
+ else
172
+ msg = args.empty? ? "" : args.first
173
+ ana = Combinator.new(&Proc.new).analyse
174
+ assert_block(build_message(msg, "#{ana}.")) { false }
175
+ end
176
+ else
177
+ super
178
+ end
179
+ end
180
+ end
181
+
182
+ end
data/tasks/notes.rake ADDED
@@ -0,0 +1,122 @@
1
+ # The following code is based on Bones 2.5.1
2
+ #
3
+
4
+ module Bones
5
+
6
+ # A helper class used to find and display any annotations in a collection of
7
+ # project files.
8
+ #
9
+ class AnnotationExtractor
10
+
11
+ class Annotation < Struct.new(:line, :tag, :text)
12
+ # Returns a string representation of the annotation. If the
13
+ # <tt>:tag</tt> parameter is given as +true+, then the annotation tag
14
+ # will be included in the string.
15
+ #
16
+ def to_s( opts = {} )
17
+ s = "[%3d] " % line
18
+ s << "[#{tag}] " if opts[:tag]
19
+ s << text
20
+ end
21
+ end
22
+
23
+ # Enumerate all the annoations for the given _project_ and _tag_. This
24
+ # will search for all athe annotations and display them on standard
25
+ # output.
26
+ #
27
+ def self.enumerate tag, id = nil, opts = {}
28
+ extractor = new(tag, id)
29
+ extractor.display(extractor.find, opts)
30
+ end
31
+
32
+ attr_reader :tag, :id
33
+
34
+ # Creates a new annotation extractor configured to use the _project_ open
35
+ # strcut and to search for the given _tag_ (which can be more than one tag
36
+ # via a regular expression 'or' operation -- i.e. THIS|THAT|OTHER)
37
+ #
38
+ def initialize tag, id
39
+ @tag = tag
40
+ @id = @id_rgxp = nil
41
+
42
+ unless id.nil? or id.empty?
43
+ @id = id
44
+ @id_rgxp = Regexp.new(Regexp.escape(id), Regexp::IGNORECASE)
45
+ end
46
+ end
47
+
48
+ # Iterate over all the files in the project and extract annotations from
49
+ # the those files. Returns the results as a hash for display.
50
+ #
51
+ def find
52
+ results = {}
53
+ rgxp = %r/(#{tag}):?\s*(.*?)(?:\s*(?:-?%>|\*+\/))?$/o
54
+
55
+ files = Dir.glob("lib/**/*.rb")
56
+ files += Dir.glob("test/**/*.rb")
57
+ files += Dir.glob("bin/*")
58
+ files.each do |fn|
59
+ results.update(extract_annotations_from(fn, rgxp))
60
+ end
61
+
62
+ results
63
+ end
64
+
65
+ # Extract any annotations from the given _file_ using the regular
66
+ # expression _pattern_ provided.
67
+ #
68
+ def extract_annotations_from( file, pattern )
69
+ lineno = 0
70
+ result = File.readlines(file).inject([]) do |list, line|
71
+ lineno += 1
72
+ next list unless m = pattern.match(line)
73
+ next list << Annotation.new(lineno, m[1], m[2]) unless id
74
+
75
+ text = m[2]
76
+ if text =~ @id_rgxp
77
+ list << Annotation.new(lineno, m[1], text)
78
+ end
79
+ list
80
+ end
81
+ result.empty? ? {} : { file => result }
82
+ end
83
+
84
+ # Print the results of the annotation extraction to the screen. If the
85
+ # <tt>:tags</tt> option is set to +true+, then the annotation tag will be
86
+ # displayed.
87
+ #
88
+ def display( results, opts = {} )
89
+ results.keys.sort.each do |file|
90
+ puts "#{file}:"
91
+ results[file].each do |note|
92
+ puts " * #{note.to_s(opts)}"
93
+ end
94
+ puts
95
+ end
96
+ end
97
+
98
+ end # class AnnotationExtractor
99
+ end # module Bones
100
+
101
+ note_tags = ["TODO", "FIXME", "OPTIMIZE"]
102
+
103
+ desc "Enumerate all annotations"
104
+ task :notes do |t|
105
+ id = if t.application.top_level_tasks.length > 1
106
+ t.application.top_level_tasks.slice!(1..-1).join(' ')
107
+ end
108
+ Bones::AnnotationExtractor.enumerate(
109
+ note_tags.join('|'), id, :tag => true)
110
+ end
111
+
112
+ namespace :notes do
113
+ note_tags.each do |tag|
114
+ desc "Enumerate all #{tag} annotations"
115
+ task tag.downcase.to_sym do |t|
116
+ id = if t.application.top_level_tasks.length > 1
117
+ t.application.top_level_tasks.slice!(1..-1).join(' ')
118
+ end
119
+ Bones::AnnotationExtractor.enumerate(tag, id)
120
+ end
121
+ end
122
+ end