anise 0.6.0 → 0.7.0

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 (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
-