psych 1.1.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 (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