psych 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/.autotest +18 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.rdoc +3 -0
  4. data/Manifest.txt +87 -0
  5. data/README.rdoc +50 -0
  6. data/Rakefile +66 -0
  7. data/ext/psych/emitter.c +517 -0
  8. data/ext/psych/emitter.h +8 -0
  9. data/ext/psych/extconf.rb +22 -0
  10. data/ext/psych/parser.c +384 -0
  11. data/ext/psych/parser.h +6 -0
  12. data/ext/psych/psych.c +34 -0
  13. data/ext/psych/psych.h +20 -0
  14. data/ext/psych/to_ruby.c +41 -0
  15. data/ext/psych/to_ruby.h +8 -0
  16. data/ext/psych/yaml_tree.c +24 -0
  17. data/ext/psych/yaml_tree.h +8 -0
  18. data/lib/psych.rb +263 -0
  19. data/lib/psych/coder.rb +94 -0
  20. data/lib/psych/core_ext.rb +39 -0
  21. data/lib/psych/deprecated.rb +82 -0
  22. data/lib/psych/handler.rb +221 -0
  23. data/lib/psych/json.rb +6 -0
  24. data/lib/psych/json/ruby_events.rb +19 -0
  25. data/lib/psych/json/stream.rb +15 -0
  26. data/lib/psych/json/tree_builder.rb +12 -0
  27. data/lib/psych/json/yaml_events.rb +29 -0
  28. data/lib/psych/nodes.rb +77 -0
  29. data/lib/psych/nodes/alias.rb +18 -0
  30. data/lib/psych/nodes/document.rb +60 -0
  31. data/lib/psych/nodes/mapping.rb +56 -0
  32. data/lib/psych/nodes/node.rb +52 -0
  33. data/lib/psych/nodes/scalar.rb +67 -0
  34. data/lib/psych/nodes/sequence.rb +81 -0
  35. data/lib/psych/nodes/stream.rb +37 -0
  36. data/lib/psych/omap.rb +4 -0
  37. data/lib/psych/parser.rb +47 -0
  38. data/lib/psych/scalar_scanner.rb +105 -0
  39. data/lib/psych/set.rb +4 -0
  40. data/lib/psych/stream.rb +36 -0
  41. data/lib/psych/streaming.rb +22 -0
  42. data/lib/psych/tree_builder.rb +94 -0
  43. data/lib/psych/visitors.rb +6 -0
  44. data/lib/psych/visitors/depth_first.rb +26 -0
  45. data/lib/psych/visitors/emitter.rb +44 -0
  46. data/lib/psych/visitors/json_tree.rb +21 -0
  47. data/lib/psych/visitors/to_ruby.rb +267 -0
  48. data/lib/psych/visitors/visitor.rb +19 -0
  49. data/lib/psych/visitors/yaml_tree.rb +373 -0
  50. data/test/psych/helper.rb +63 -0
  51. data/test/psych/json/test_stream.rb +109 -0
  52. data/test/psych/nodes/test_enumerable.rb +43 -0
  53. data/test/psych/test_alias_and_anchor.rb +26 -0
  54. data/test/psych/test_array.rb +19 -0
  55. data/test/psych/test_boolean.rb +36 -0
  56. data/test/psych/test_class.rb +17 -0
  57. data/test/psych/test_coder.rb +184 -0
  58. data/test/psych/test_date_time.rb +17 -0
  59. data/test/psych/test_deprecated.rb +210 -0
  60. data/test/psych/test_document.rb +46 -0
  61. data/test/psych/test_emitter.rb +94 -0
  62. data/test/psych/test_encoding.rb +179 -0
  63. data/test/psych/test_engine_manager.rb +57 -0
  64. data/test/psych/test_exception.rb +39 -0
  65. data/test/psych/test_hash.rb +30 -0
  66. data/test/psych/test_json_tree.rb +65 -0
  67. data/test/psych/test_merge_keys.rb +72 -0
  68. data/test/psych/test_nil.rb +18 -0
  69. data/test/psych/test_null.rb +19 -0
  70. data/test/psych/test_object.rb +27 -0
  71. data/test/psych/test_omap.rb +68 -0
  72. data/test/psych/test_parser.rb +297 -0
  73. data/test/psych/test_psych.rb +168 -0
  74. data/test/psych/test_scalar.rb +11 -0
  75. data/test/psych/test_scalar_scanner.rb +69 -0
  76. data/test/psych/test_serialize_subclasses.rb +38 -0
  77. data/test/psych/test_set.rb +49 -0
  78. data/test/psych/test_stream.rb +49 -0
  79. data/test/psych/test_string.rb +49 -0
  80. data/test/psych/test_struct.rb +51 -0
  81. data/test/psych/test_symbol.rb +17 -0
  82. data/test/psych/test_to_yaml_properties.rb +63 -0
  83. data/test/psych/test_tree_builder.rb +79 -0
  84. data/test/psych/test_yaml.rb +1256 -0
  85. data/test/psych/visitors/test_depth_first.rb +49 -0
  86. data/test/psych/visitors/test_emitter.rb +144 -0
  87. data/test/psych/visitors/test_to_ruby.rb +325 -0
  88. data/test/psych/visitors/test_yaml_tree.rb +155 -0
  89. metadata +232 -0
@@ -0,0 +1,39 @@
1
+ class Object
2
+ def self.yaml_tag url
3
+ Psych.add_tag(url, self)
4
+ end
5
+
6
+ # FIXME: rename this to "to_yaml" when syck is removed
7
+
8
+ ###
9
+ # call-seq: to_yaml(options = {})
10
+ #
11
+ # Convert an object to YAML. See Psych.dump for more information on the
12
+ # available +options+.
13
+ def psych_to_yaml options = {}
14
+ Psych.dump self, options
15
+ end
16
+ remove_method :to_yaml rescue nil
17
+ alias :to_yaml :psych_to_yaml
18
+ end
19
+
20
+ class Module
21
+ def psych_yaml_as url
22
+ return if caller[0].end_with?('rubytypes.rb')
23
+ if $VERBOSE
24
+ warn "#{caller[0]}: yaml_as is deprecated, please use yaml_tag"
25
+ end
26
+ Psych.add_tag(url, self)
27
+ end
28
+
29
+ remove_method :yaml_as rescue nil
30
+ alias :yaml_as :psych_yaml_as
31
+ end
32
+
33
+ module Kernel
34
+ def psych_y *objects
35
+ puts Psych.dump_stream(*objects)
36
+ end
37
+ remove_method :y rescue nil
38
+ alias y psych_y
39
+ end
@@ -0,0 +1,82 @@
1
+ require 'date'
2
+
3
+ module Psych
4
+ DEPRECATED = __FILE__ # :nodoc:
5
+
6
+ module DeprecatedMethods # :nodoc:
7
+ attr_accessor :taguri
8
+ attr_accessor :to_yaml_style
9
+ end
10
+
11
+ def self.quick_emit thing, opts = {}, &block # :nodoc:
12
+ warn "#{caller[0]}: YAML.quick_emit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
13
+ target = eval 'self', block.binding
14
+ target.extend DeprecatedMethods
15
+ metaclass = class << target; self; end
16
+ metaclass.send(:define_method, :encode_with) do |coder|
17
+ target.taguri = coder.tag
18
+ target.to_yaml_style = coder.style
19
+ block.call coder
20
+ end
21
+ target.psych_to_yaml unless opts[:nodump]
22
+ end
23
+
24
+ def self.load_documents yaml, &block
25
+ if $VERBOSE
26
+ warn "#{caller[0]}: load_documents is deprecated, use load_stream"
27
+ end
28
+ list = load_stream yaml
29
+ return list unless block_given?
30
+ list.each(&block)
31
+ end
32
+
33
+ def self.detect_implicit thing
34
+ warn "#{caller[0]}: detect_implicit is deprecated" if $VERBOSE
35
+ return '' unless String === thing
36
+ return 'null' if '' == thing
37
+ ScalarScanner.new.tokenize(thing).class.name.downcase
38
+ end
39
+
40
+ def self.add_ruby_type type_tag, &block
41
+ warn "#{caller[0]}: add_ruby_type is deprecated, use add_domain_type" if $VERBOSE
42
+ domain = 'ruby.yaml.org,2002'
43
+ key = ['tag', domain, type_tag].join ':'
44
+ @domain_types[key] = [key, block]
45
+ end
46
+
47
+ def self.add_private_type type_tag, &block
48
+ warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE
49
+ domain = 'x-private'
50
+ key = [domain, type_tag].join ':'
51
+ @domain_types[key] = [key, block]
52
+ end
53
+
54
+ def self.tagurize thing
55
+ warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE
56
+ return thing unless String === thing
57
+ "tag:yaml.org,2002:#{thing}"
58
+ end
59
+
60
+ def self.read_type_class type, reference
61
+ warn "#{caller[0]}: read_type_class is deprecated" if $VERBOSE
62
+ _, _, type, name = type.split ':', 4
63
+
64
+ reference = name.split('::').inject(reference) do |k,n|
65
+ k.const_get(n.to_sym)
66
+ end if name
67
+ [type, reference]
68
+ end
69
+
70
+ def self.object_maker klass, hash
71
+ warn "#{caller[0]}: object_maker is deprecated" if $VERBOSE
72
+ klass.allocate.tap do |obj|
73
+ hash.each { |k,v| obj.instance_variable_set(:"@#{k}", v) }
74
+ end
75
+ end
76
+ end
77
+
78
+ class Object
79
+ def to_yaml_properties # :nodoc:
80
+ instance_variables
81
+ end
82
+ end
@@ -0,0 +1,221 @@
1
+ module Psych
2
+ ###
3
+ # Psych::Handler is an abstract base class that defines the events used
4
+ # when dealing with Psych::Parser. Clients who want to use Psych::Parser
5
+ # should implement a class that inherits from Psych::Handler and define
6
+ # events that they can handle.
7
+ #
8
+ # Psych::Handler defines all events that Psych::Parser can possibly send to
9
+ # event handlers.
10
+ #
11
+ # See Psych::Parser for more details
12
+ class Handler
13
+ ###
14
+ # Called with +encoding+ when the YAML stream starts. This method is
15
+ # called once per stream. A stream may contain multiple documents.
16
+ #
17
+ # See the constants in Psych::Parser for the possible values of +encoding+.
18
+ def start_stream encoding
19
+ end
20
+
21
+ ###
22
+ # Called when the document starts with the declared +version+,
23
+ # +tag_directives+, if the document is +implicit+.
24
+ #
25
+ # +version+ will be an array of integers indicating the YAML version being
26
+ # dealt with, +tag_directives+ is a list of tuples indicating the prefix
27
+ # and suffix of each tag, and +implicit+ is a boolean indicating whether
28
+ # the document is started implicitly.
29
+ #
30
+ # === Example
31
+ #
32
+ # Given the following YAML:
33
+ #
34
+ # %YAML 1.1
35
+ # %TAG ! tag:tenderlovemaking.com,2009:
36
+ # --- !squee
37
+ #
38
+ # The parameters for start_document must be this:
39
+ #
40
+ # version # => [1, 1]
41
+ # tag_directives # => [["!", "tag:tenderlovemaking.com,2009:"]]
42
+ # implicit # => false
43
+ def start_document version, tag_directives, implicit
44
+ end
45
+
46
+ ###
47
+ # Called with the document ends. +implicit+ is a boolean value indicating
48
+ # whether or not the document has an implicit ending.
49
+ #
50
+ # === Example
51
+ #
52
+ # Given the following YAML:
53
+ #
54
+ # ---
55
+ # hello world
56
+ #
57
+ # +implicit+ will be true. Given this YAML:
58
+ #
59
+ # ---
60
+ # hello world
61
+ # ...
62
+ #
63
+ # +implicit+ will be false.
64
+ def end_document implicit
65
+ end
66
+
67
+ ###
68
+ # Called when an alias is found to +anchor+. +anchor+ will be the name
69
+ # of the anchor found.
70
+ #
71
+ # === Example
72
+ #
73
+ # Here we have an example of an array that references itself in YAML:
74
+ #
75
+ # --- &ponies
76
+ # - first element
77
+ # - *ponies
78
+ #
79
+ # &ponies is the achor, *ponies is the alias. In this case, alias is
80
+ # called with "ponies".
81
+ def alias anchor
82
+ end
83
+
84
+ ###
85
+ # Called when a scalar +value+ is found. The scalar may have an
86
+ # +anchor+, a +tag+, be implicitly +plain+ or implicitly +quoted+
87
+ #
88
+ # +value+ is the string value of the scalar
89
+ # +anchor+ is an associated anchor or nil
90
+ # +tag+ is an associated tag or nil
91
+ # +plain+ is a boolean value
92
+ # +quoted+ is a boolean value
93
+ # +style+ is an integer idicating the string style
94
+ #
95
+ # See the constants in Psych::Nodes::Scalar for the possible values of
96
+ # +style+
97
+ #
98
+ # === Example
99
+ #
100
+ # Here is a YAML document that exercises most of the possible ways this
101
+ # method can be called:
102
+ #
103
+ # ---
104
+ # - !str "foo"
105
+ # - &anchor fun
106
+ # - many
107
+ # lines
108
+ # - |
109
+ # many
110
+ # newlines
111
+ #
112
+ # The above YAML document contains a list with four strings. Here are
113
+ # the parameters sent to this method in the same order:
114
+ #
115
+ # # value anchor tag plain quoted style
116
+ # ["foo", nil, "!str", false, false, 3 ]
117
+ # ["fun", "anchor", nil, true, false, 1 ]
118
+ # ["many lines", nil, nil, true, false, 1 ]
119
+ # ["many\nnewlines\n", nil, nil, false, true, 4 ]
120
+ #
121
+ def scalar value, anchor, tag, plain, quoted, style
122
+ end
123
+
124
+ ###
125
+ # Called when a sequence is started.
126
+ #
127
+ # +anchor+ is the anchor associated with the sequence or nil.
128
+ # +tag+ is the tag associated with the sequence or nil.
129
+ # +implicit+ a boolean indicating whether or not the sequence was implicitly
130
+ # started.
131
+ # +style+ is an integer indicating the list style.
132
+ #
133
+ # See the constants in Psych::Nodes::Sequence for the possible values of
134
+ # +style+.
135
+ #
136
+ # === Example
137
+ #
138
+ # Here is a YAML document that exercises most of the possible ways this
139
+ # method can be called:
140
+ #
141
+ # ---
142
+ # - !!seq [
143
+ # a
144
+ # ]
145
+ # - &pewpew
146
+ # - b
147
+ #
148
+ # The above YAML document consists of three lists, an outer list that
149
+ # contains two inner lists. Here is a matrix of the parameters sent
150
+ # to represent these lists:
151
+ #
152
+ # # anchor tag implicit style
153
+ # [nil, nil, true, 1 ]
154
+ # [nil, "tag:yaml.org,2002:seq", false, 2 ]
155
+ # ["pewpew", nil, true, 1 ]
156
+
157
+ def start_sequence anchor, tag, implicit, style
158
+ end
159
+
160
+ ###
161
+ # Called when a sequence ends.
162
+ def end_sequence
163
+ end
164
+
165
+ ###
166
+ # Called when a map starts.
167
+ #
168
+ # +anchor+ is the anchor associated with the map or +nil+.
169
+ # +tag+ is the tag associated with the map or +nil+.
170
+ # +implicit+ is a boolean indicating whether or not the map was implicitly
171
+ # started.
172
+ # +style+ is an integer indicating the mapping style.
173
+ #
174
+ # See the constants in Psych::Nodes::Mapping for the possible values of
175
+ # +style+.
176
+ #
177
+ # === Example
178
+ #
179
+ # Here is a YAML document that exercises most of the possible ways this
180
+ # method can be called:
181
+ #
182
+ # ---
183
+ # k: !!map { hello: world }
184
+ # v: &pewpew
185
+ # hello: world
186
+ #
187
+ # The above YAML document consists of three maps, an outer map that contains
188
+ # two inner maps. Below is a matrix of the parameters sent in order to
189
+ # represent these three maps:
190
+ #
191
+ # # anchor tag implicit style
192
+ # [nil, nil, true, 1 ]
193
+ # [nil, "tag:yaml.org,2002:map", false, 2 ]
194
+ # ["pewpew", nil, true, 1 ]
195
+
196
+ def start_mapping anchor, tag, implicit, style
197
+ end
198
+
199
+ ###
200
+ # Called when a map ends
201
+ def end_mapping
202
+ end
203
+
204
+ ###
205
+ # Called when an empty event happens. (Which, as far as I can tell, is
206
+ # never).
207
+ def empty
208
+ end
209
+
210
+ ###
211
+ # Called when the YAML stream ends
212
+ def end_stream
213
+ end
214
+
215
+ ###
216
+ # Is this handler a streaming handler?
217
+ def streaming?
218
+ false
219
+ end
220
+ end
221
+ end
data/lib/psych/json.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Psych
2
+ module JSON
3
+ autoload :TreeBuilder, 'psych/json/tree_builder'
4
+ autoload :Stream, 'psych/json/stream'
5
+ end
6
+ end
@@ -0,0 +1,19 @@
1
+ module Psych
2
+ module JSON
3
+ module RubyEvents # :nodoc:
4
+ def visit_Time o
5
+ formatted = format_time o
6
+ @emitter.scalar formatted, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED
7
+ end
8
+
9
+ def visit_DateTime o
10
+ visit_Time o.to_time
11
+ end
12
+
13
+ def visit_String o
14
+ @emitter.scalar o.to_s, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED
15
+ end
16
+ alias :visit_Symbol :visit_String
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ require 'psych/json/ruby_events'
2
+ require 'psych/json/yaml_events'
3
+
4
+ module Psych
5
+ module JSON
6
+ class Stream < Psych::Visitors::JSONTree
7
+ include Psych::JSON::RubyEvents
8
+ include Psych::Streaming
9
+
10
+ class Emitter < Psych::Stream::Emitter # :nodoc:
11
+ include Psych::JSON::YAMLEvents
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ require 'psych/json/yaml_events'
2
+
3
+ module Psych
4
+ module JSON
5
+ ###
6
+ # Psych::JSON::TreeBuilder is an event based AST builder. Events are sent
7
+ # to an instance of Psych::JSON::TreeBuilder and a JSON AST is constructed.
8
+ class TreeBuilder < Psych::TreeBuilder
9
+ include Psych::JSON::YAMLEvents
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,29 @@
1
+ module Psych
2
+ module JSON
3
+ module YAMLEvents # :nodoc:
4
+ def start_document version, tag_directives, implicit
5
+ super(version, tag_directives, !streaming?)
6
+ end
7
+
8
+ def end_document implicit_end = !streaming?
9
+ super(implicit_end)
10
+ end
11
+
12
+ def start_mapping anchor, tag, implicit, style
13
+ super(anchor, nil, implicit, Nodes::Mapping::FLOW)
14
+ end
15
+
16
+ def start_sequence anchor, tag, implicit, style
17
+ super(anchor, nil, implicit, Nodes::Sequence::FLOW)
18
+ end
19
+
20
+ def scalar value, anchor, tag, plain, quoted, style
21
+ if "tag:yaml.org,2002:null" == tag
22
+ super('null', nil, nil, true, false, Nodes::Scalar::PLAIN)
23
+ else
24
+ super
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,77 @@
1
+ require 'psych/nodes/node'
2
+ require 'psych/nodes/stream'
3
+ require 'psych/nodes/document'
4
+ require 'psych/nodes/sequence'
5
+ require 'psych/nodes/scalar'
6
+ require 'psych/nodes/mapping'
7
+ require 'psych/nodes/alias'
8
+
9
+ module Psych
10
+ ###
11
+ # = Overview
12
+ #
13
+ # When using Psych.load to deserialize a YAML document, the document is
14
+ # translated to an intermediary AST. That intermediary AST is then
15
+ # translated in to a Ruby object graph.
16
+ #
17
+ # In the opposite direction, when using Psych.dump, the Ruby object graph is
18
+ # translated to an intermediary AST which is then converted to a YAML
19
+ # document.
20
+ #
21
+ # Psych::Nodes contains all of the classes that make up the nodes of a YAML
22
+ # AST. You can manually build an AST and use one of the visitors (see
23
+ # Psych::Visitors) to convert that AST to either a YAML document or to a
24
+ # Ruby object graph.
25
+ #
26
+ # Here is an example of building an AST that represents a list with one
27
+ # scalar:
28
+ #
29
+ # # Create our nodes
30
+ # stream = Psych::Nodes::Stream.new
31
+ # doc = Psych::Nodes::Document.new
32
+ # seq = Psych::Nodes::Sequence.new
33
+ # scalar = Psych::Nodes::Scalar.new('foo')
34
+ #
35
+ # # Build up our tree
36
+ # stream.children << doc
37
+ # doc.children << seq
38
+ # seq.children << scalar
39
+ #
40
+ # The stream is the root of the tree. We can then convert the tree to YAML:
41
+ #
42
+ # stream.to_yaml => "---\n- foo\n"
43
+ #
44
+ # Or convert it to Ruby:
45
+ #
46
+ # stream.to_ruby => [["foo"]]
47
+ #
48
+ # == YAML AST Requirements
49
+ #
50
+ # A valid YAML AST *must* have one Psych::Nodes::Stream at the root. A
51
+ # Psych::Nodes::Stream node must have 1 or more Psych::Nodes::Document nodes
52
+ # as children.
53
+ #
54
+ # Psych::Nodes::Document nodes must have one and *only* one child. That child
55
+ # may be one of:
56
+ #
57
+ # * Psych::Nodes::Sequence
58
+ # * Psych::Nodes::Mapping
59
+ # * Psych::Nodes::Scalar
60
+ #
61
+ # Psych::Nodes::Sequence and Psych::Nodes::Mapping nodes may have many
62
+ # children, but Psych::Nodes::Mapping nodes should have an even number of
63
+ # children.
64
+ #
65
+ # All of these are valid children for Psych::Nodes::Sequence and
66
+ # Psych::Nodes::Mapping nodes:
67
+ #
68
+ # * Psych::Nodes::Sequence
69
+ # * Psych::Nodes::Mapping
70
+ # * Psych::Nodes::Scalar
71
+ # * Psych::Nodes::Alias
72
+ #
73
+ # Psych::Nodes::Scalar and Psych::Nodes::Alias are both terminal nodes and
74
+ # should not have any children.
75
+ module Nodes
76
+ end
77
+ end