anise 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.ruby +59 -38
  2. data/.yardopts +7 -0
  3. data/DEMO.md +242 -0
  4. data/{HISTORY.rdoc → HISTORY.md} +28 -7
  5. data/LICENSE.txt +27 -0
  6. data/README.md +129 -0
  7. data/demo/01_annotations.md +81 -0
  8. data/demo/03_attributes.md +14 -0
  9. data/demo/04_methods.md +50 -0
  10. data/demo/05_variables.md +45 -0
  11. data/{qed → demo}/applique/ae.rb +0 -0
  12. data/demo/applique/anise.rb +1 -0
  13. data/{qed/toplevel/01_annotations.qed → demo/toplevel/01_annotations.md} +5 -9
  14. data/demo/toplevel/03_attributes.md +20 -0
  15. data/lib/anise.rb +28 -45
  16. data/lib/anise.yml +59 -38
  17. data/lib/anise/annotations.rb +132 -0
  18. data/lib/anise/annotations/store.rb +136 -0
  19. data/lib/anise/annotative.rb +7 -0
  20. data/lib/anise/annotative/attributes.rb +147 -0
  21. data/lib/anise/annotative/methods.rb +131 -0
  22. data/lib/anise/annotative/variables.rb +99 -0
  23. data/lib/anise/{module.rb → core_ext.rb} +30 -0
  24. data/lib/anise/universal.rb +6 -0
  25. data/lib/anise/version.rb +17 -0
  26. data/test/case_annotations.rb +173 -0
  27. data/test/case_attributes.rb +46 -0
  28. data/test/case_combined_usage.rb +341 -0
  29. data/test/case_methods.rb +36 -0
  30. data/test/case_variables.rb +22 -0
  31. data/test/helper.rb +2 -0
  32. metadata +99 -98
  33. data/APACHE2.txt +0 -204
  34. data/COPYING.rdoc +0 -17
  35. data/README.rdoc +0 -107
  36. data/lib/anise/annotation.rb +0 -175
  37. data/lib/anise/annotator.rb +0 -82
  38. data/lib/anise/attribute.rb +0 -138
  39. data/qed/01_annotations.qed +0 -26
  40. data/qed/02_annotation_added.rdoc +0 -60
  41. data/qed/03_attributes.rdoc +0 -16
  42. data/qed/04_annotator.rdoc +0 -49
  43. data/qed/toplevel/03_attributes.rdoc +0 -20
  44. data/test/suite.rb +0 -8
  45. data/test/test_anise.rb +0 -193
  46. data/test/test_anise_toplevel.rb +0 -194
  47. data/test/test_annotations.rb +0 -136
  48. data/test/test_annotations_module.rb +0 -132
  49. data/test/test_annotations_toplevel.rb +0 -131
  50. data/test/test_annotator.rb +0 -26
  51. data/test/test_annotator_toplevel.rb +0 -28
  52. data/test/test_attribute.rb +0 -37
  53. data/test/test_attribute_toplevel.rb +0 -65
@@ -0,0 +1,129 @@
1
+ # Anise
2
+
3
+ [Hompage](http://rubyworks.github.com/anise) /
4
+ [Report Issue](http://github.com/rubyworks/anise/issues) /
5
+ [Source Code](http://github.com/rubyworks/anise) /
6
+ [Mailing List](http://groups.google.com/group/rubyworks-mailinglist) /
7
+ [IRC Channel](http://chat.us.freenode.new/rubyworks)
8
+
9
+ [![Build Status](https://secure.travis-ci.org/rubyworks/anise.png)](http://travis-ci.org/rubyworks/anise)
10
+
11
+
12
+ ## Introduction
13
+
14
+ Anise is an Annotation System for the Ruby programming language.
15
+ Unlike most other annotations systems it is not a comment-based or
16
+ macro-based system that sits over-and-above the rest of the code.
17
+ Rather, Anise is a dynamic annotations system operating at runtime.
18
+
19
+
20
+ ## Installation
21
+
22
+ To install with RubyGems simply open a console and type:
23
+
24
+ gem install anise
25
+
26
+ To manually install you will need Setup.rb (see http://setup.rubyforge.org).
27
+ Then download the tarball package and do:
28
+
29
+ $ tar -xvzf anise-0.2.0.tgz
30
+ $ cd anise-0.2.0
31
+ $ sudo setup.rb all
32
+
33
+
34
+ ## Instruction
35
+
36
+ The following example briefly demonstrates all three major features. To use
37
+ any of them first require the `anise` library.
38
+
39
+ require 'anise'
40
+
41
+ General annotations are provided by the `Anise::Annotations` module.
42
+
43
+ class X
44
+ extend Anise::Annotations
45
+
46
+ ann :grape, :class=>String
47
+ end
48
+
49
+ X.ann(:grape, :class) #=> String
50
+
51
+ Annotated attributes can be easily added to a class via the `Annotative::Attributes`
52
+ module.
53
+
54
+ class X
55
+ extend Anise::Annotative::Attributes
56
+
57
+ attr :baz, Integer, :max => 10
58
+ end
59
+
60
+ X.ann(:baz) #=> {:class=>Integer, :max=>10}
61
+
62
+ Mewthod annotations can be had via the `AnnotatedMethods` module.
63
+
64
+ class X
65
+ extend Anise::Annotative::Methods
66
+
67
+ def self.doc(string)
68
+ method_annotation(:doc=>string)
69
+ end
70
+
71
+ doc "This is an entry."
72
+
73
+ def bar
74
+ # ...
75
+ end
76
+ end
77
+
78
+ X.ann(:bar) #=> {:doc=>"This is an entry."}
79
+
80
+ Any of these modules can be used in conjunction. Since both `AnnotatedMethods`
81
+ and `AnnotatedAttributes` preclude `Annotations` all three can be used by simply
82
+ using the later two.
83
+
84
+ class X
85
+ extend Anise::Annotative::Attributes
86
+ extend Anise::Annotative::Methods
87
+
88
+ ...
89
+ end
90
+
91
+ Note also that the `Anise` module is clean and contains only modules and classes
92
+ with detailed names starting the "Annotat-", so it is prefectly convenient for
93
+ inclusion in the toplevel namespace or your own applications namespace.
94
+
95
+ module MyApp
96
+ include Anise
97
+
98
+ class Foo
99
+ extend Annotative::Attributes
100
+
101
+ ...
102
+ end
103
+ end
104
+
105
+
106
+ ## Development
107
+
108
+ ### Test Instructions
109
+
110
+ Ainse has two test suites, one using [QED](http://rubyworks.github.com/qed) and
111
+ the other using [Citron](http://rubyworks.github.com/citron) which is built on
112
+ [RubyTest](http://rubyworks.github.com/rubytest).
113
+
114
+ To run the QED demonstrations simple run:
115
+
116
+ $ qed
117
+
118
+ To run the Citron-based unit tests use:
119
+
120
+ $ rubytest
121
+
122
+
123
+ ## Copyrights
124
+
125
+ Copyright (c) 2008 Rubyworks. All rights reserved.
126
+
127
+ This program is distributed under the terms of the **BSD-2-Clause** license.
128
+
129
+ See LICNESE.txt file for details.
@@ -0,0 +1,81 @@
1
+ # Annotations
2
+
3
+ ## Creating and Reading Annotations
4
+
5
+ Load the Anise library.
6
+
7
+ require 'anise'
8
+
9
+ Given an example class X we can apply annotations to it using the #ann method.
10
+
11
+ class X
12
+ extend Anise::Annotations
13
+
14
+ ann :x1, :a=>1
15
+ ann :x1, :b=>2
16
+ end
17
+
18
+ We can then use #ann to lookup the set annotations.
19
+
20
+ X.ann(:x1,:a).should == 1
21
+
22
+ The #ann method is a public interface, so we can define annotation externally as well.
23
+
24
+ X.ann :x1, :a => 2
25
+ X.ann(:x1, :a).should == 2
26
+
27
+ ## Annotation Added Callback
28
+
29
+ Given a sample class Y, we can use a standard callback method #annotation_added().
30
+
31
+ class Y
32
+ extend Anise::Annotations
33
+
34
+ class << self
35
+ attr :last_callback
36
+
37
+ def annotation_added(ref, ns)
38
+ @last_callback = [ns, ref, ann(ref/ns)]
39
+ end
40
+ end
41
+ end
42
+
43
+ Now if we add an annotation, we will see the callback catches it.
44
+
45
+ Y.ann :x1, :a=>1
46
+ Y.last_callback.should == [:ann, :x1, {:a => 1}]
47
+
48
+ We will do it again to be sure.
49
+
50
+ Y.ann :x1, :b=>2
51
+ Y.last_callback.should == [:ann, :x1, {:a => 1, :b => 2}]
52
+
53
+ ## Using Callbacks for Attribute Defaults
54
+
55
+ class ::Module
56
+ def annotation_added(key, ns)
57
+ return unless ns == :ann
58
+ base = self
59
+ if value = ann(key, :default)
60
+ define_method(key) do
61
+ instance_variable_set("@#{key}", value) unless instance_variable_defined?("@#{key}")
62
+ base.module_eval{ attr key }
63
+ instance_variable_get("@#{key}")
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ Try it out.
70
+
71
+ class Z
72
+ extend Anise::Annotations
73
+
74
+ attr :a
75
+ ann :a, :default => 10
76
+ end
77
+
78
+ z = Z.new
79
+ z.a.should == 10
80
+ z.a.should == 10
81
+
@@ -0,0 +1,14 @@
1
+ # Annotative Attributes
2
+
3
+ Create a class that uses the `Annotative::Attributes` mixin.
4
+
5
+ class X
6
+ extend Anise::Annotative::Attributes
7
+
8
+ attr :a, :count => 1
9
+ end
10
+
11
+ Then we can see tht the attribute method `:a` has an annotation entry.
12
+
13
+ X.ann(:a, :count) #=> 1
14
+
@@ -0,0 +1,50 @@
1
+ # Method Annotations
2
+
3
+ Create a class that uses the `Annotative::Methods` mixin.
4
+
5
+ class X
6
+ extend Anise::Annotative::Methods
7
+
8
+ def self.doc(string)
9
+ method_annotation(:doc=>string.to_s)
10
+ end
11
+
12
+ doc "See what I mean?"
13
+
14
+ def see
15
+ puts "Yes, I see!"
16
+ end
17
+ end
18
+
19
+ See that it is set.
20
+
21
+ X.ann(:see, :doc) #=> "See what I mean?"
22
+
23
+ Method Annotators can override the standard annotation procedure
24
+ with a custom procedure. In such case no annotations will actually
25
+ be created unless the `#ann` is called in the procedure.
26
+
27
+ class Y
28
+ extend Anise::Annotative::Methods
29
+
30
+ def self.list
31
+ @list ||= []
32
+ end
33
+
34
+ def self.doc(string)
35
+ method_annotation do |method|
36
+ list << [method, string]
37
+ end
38
+ end
39
+
40
+ doc "See here!"
41
+
42
+ def see
43
+ puts "Yes, I see!"
44
+ end
45
+ end
46
+
47
+ See that it is set.
48
+
49
+ Y.list #=> [[:see, "See here!"]]
50
+
@@ -0,0 +1,45 @@
1
+ # Variable Annotations
2
+
3
+ Create a class that uses the `Annotative::Variables` mixin.
4
+
5
+ class X
6
+ extend Anise::Annotative::Variables
7
+
8
+ variable_annotator :@doc
9
+
10
+ @doc = "See what I mean?"
11
+
12
+ def see
13
+ puts "Yes, I see!"
14
+ end
15
+ end
16
+
17
+ See that it is set.
18
+
19
+ X.ann(:see, :@doc).should == "See what I mean?"
20
+
21
+ Variable annotations can override the standard annotation procedure with a
22
+ custom procedure.
23
+
24
+ class Y
25
+ extend Anise::Annotative::Variables
26
+
27
+ def self.list
28
+ @list ||= []
29
+ end
30
+
31
+ variable_annotator :@doc do |method, value|
32
+ list << [method, value]
33
+ end
34
+
35
+ @doc = "See here!"
36
+
37
+ def see
38
+ puts "Yes, I see!"
39
+ end
40
+ end
41
+
42
+ See that it is set.
43
+
44
+ Y.list #=> [[:see, "See here!"]]
45
+
File without changes
@@ -0,0 +1 @@
1
+ require 'anise'
@@ -1,13 +1,9 @@
1
- = Creating and Reading Annotations
1
+ = TOPLEVEL Annotations
2
2
 
3
- Load the primary annotations library.
4
-
5
- require 'anise/annotation'
6
-
7
- Including Annotations at the toplevel should make them available to all classes.
3
+ Extending Object with `Annotations` should make them available to all classes.
8
4
 
9
5
  class ::Object
10
- include Anise::Annotation
6
+ extend Anise::Annotations
11
7
  end
12
8
 
13
9
  Given a example class X we can apply annotations to it using the #ann method.
@@ -19,12 +15,12 @@ Given a example class X we can apply annotations to it using the #ann method.
19
15
 
20
16
  We can then use #ann to lookup the set annotations.
21
17
 
22
- X.ann(:x1,:a).should == 1
18
+ X.ann(:x1,:a).should == 1
23
19
 
24
20
  The #ann method is a public interface, so we can define annotation externally as well.
25
21
 
26
22
  X.ann :x1, :a => 2
27
23
  X.ann(:x1, :a).should == 2
28
24
 
29
- QED.
25
+ Alternatively the `Annotations` module could be included into the `Module` class.
30
26
 
@@ -0,0 +1,20 @@
1
+ = TOPLEVEL Annotated Attributes
2
+
3
+ Including `AnnotatedAttributes` at the toplevel, i.e. Object, will make
4
+ annotated attributes univerally available.
5
+
6
+ class ::Object
7
+ extend Anise::Annotative::Attributes
8
+ end
9
+
10
+ Create a class that uses it.
11
+
12
+ class X
13
+ attr :a, :count=>1
14
+ end
15
+
16
+ X.ann(:a, :count) #=> 1
17
+
18
+ Alternatively the `Annotative::Attributes` module could be included into
19
+ the `Module` class.
20
+
@@ -1,62 +1,45 @@
1
- require 'anise/annotation'
2
- require 'anise/attribute'
3
- require 'anise/annotator'
4
-
5
- # = Anise
6
- #
7
1
  # Dynamic Annotations for Ruby.
8
2
  #
9
3
  # require 'anise'
10
4
  #
5
+ # Provides annotations:
6
+ #
11
7
  # class X
12
- # include Anise
8
+ # extend Anise::Annotations
13
9
  #
14
- # # Provides annotations
15
10
  # ann :foo, :class=>String
11
+ # end
16
12
  #
17
- # # Provides annotated attributes
18
- # attr :bar, Integer, :max=>10
13
+ # Provides method annotations:
14
+ #
15
+ # class Y
16
+ # extend Anise::Annotator::Method
17
+ #
18
+ # def self.doc(string)
19
+ # method_annotation(:doc=>string)
20
+ # end
19
21
  #
20
- # # Provides method annotators.
21
- # annotator :doc
22
22
  # doc "foo is cool"
23
23
  # def foo
24
24
  # # ...
25
25
  # end
26
26
  # end
27
27
  #
28
+ # Provides annotated attributes:
29
+ #
30
+ # class Z
31
+ # extend Anise::Annotator::Attribute
32
+ #
33
+ # attr :bar, Integer, :max=>10
34
+ # end
35
+ #
28
36
  module Anise
29
- extend self
30
-
31
- def included(base)
32
- #super(base)
33
- base.send(:include, Attribute)
34
- base.send(:include, Annotator)
35
- #base.extend Anise #ClassMethods
36
- end
37
-
38
- #module ClassMethods
39
- # def append_features(base)
40
- # super(base)
41
- # Attribute.append_features(base)
42
- # Annotator.append_features(base)
43
- # base.extend ClassMethods
44
- # end
45
- #end
46
-
47
- #
48
- def self.metadata
49
- @metadata ||= (
50
- require 'yaml'
51
- YAML.load(File.new(File.dirname(__FILE__) + '/anise.yml'))
52
- )
53
- end
54
-
55
- #
56
- def self.const_missing(name)
57
- metadata[name.to_s.downcase] || super(name)
58
- end
59
-
60
- VERSION = metadata['version'] # becuase Ruby 1.8~ gets in the way :(
37
+ require 'anise/version'
38
+ require 'anise/core_ext'
39
+ require 'anise/annotations'
40
+ require 'anise/annotations/store'
41
+ require 'anise/annotative'
42
+ require 'anise/annotative/methods'
43
+ require 'anise/annotative/attributes'
44
+ require 'anise/annotative/variables'
61
45
  end
62
-