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
data/ext/psych/psych.h ADDED
@@ -0,0 +1,20 @@
1
+ #ifndef PSYCH_H
2
+ #define PSYCH_H
3
+
4
+ #include <ruby.h>
5
+
6
+ #ifdef HAVE_RUBY_ENCODING_H
7
+ #include <ruby/encoding.h>
8
+ #endif
9
+
10
+ #include <yaml.h>
11
+
12
+ #include <parser.h>
13
+ #include <emitter.h>
14
+ #include <to_ruby.h>
15
+ #include <yaml_tree.h>
16
+
17
+ extern VALUE mPsych;
18
+
19
+
20
+ #endif
@@ -0,0 +1,41 @@
1
+ #include <psych.h>
2
+
3
+ VALUE cPsychVisitorsToRuby;
4
+
5
+ /* call-seq: vis.build_exception(klass, message)
6
+ *
7
+ * Create an exception with class +klass+ and +message+
8
+ */
9
+ static VALUE build_exception(VALUE self, VALUE klass, VALUE mesg)
10
+ {
11
+ VALUE e = rb_obj_alloc(klass);
12
+
13
+ rb_iv_set(e, "mesg", mesg);
14
+
15
+ return e;
16
+ }
17
+
18
+ /* call-seq: vis.path2class(path)
19
+ *
20
+ * Convert +path+ string to a class
21
+ */
22
+ static VALUE path2class(VALUE self, VALUE path)
23
+ {
24
+ #ifdef HAVE_RUBY_ENCODING_H
25
+ return rb_path_to_class(path);
26
+ #else
27
+ return rb_path2class(StringValuePtr(path));
28
+ #endif
29
+ }
30
+
31
+ void Init_psych_to_ruby(void)
32
+ {
33
+ VALUE psych = rb_define_module("Psych");
34
+ VALUE visitors = rb_define_module_under(psych, "Visitors");
35
+ VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject);
36
+ cPsychVisitorsToRuby = rb_define_class_under(visitors, "ToRuby", visitor);
37
+
38
+ rb_define_private_method(cPsychVisitorsToRuby, "build_exception", build_exception, 2);
39
+ rb_define_private_method(cPsychVisitorsToRuby, "path2class", path2class, 1);
40
+ }
41
+ /* vim: set noet sws=4 sw=4: */
@@ -0,0 +1,8 @@
1
+ #ifndef PSYCH_TO_RUBY_H
2
+ #define PSYCH_TO_RUBY_H
3
+
4
+ #include <psych.h>
5
+
6
+ void Init_psych_to_ruby(void);
7
+
8
+ #endif
@@ -0,0 +1,24 @@
1
+ #include <psych.h>
2
+
3
+ VALUE cPsychVisitorsYamlTree;
4
+
5
+ /*
6
+ * call-seq: private_iv_get(target, prop)
7
+ *
8
+ * Get the private instance variable +prop+ from +target+
9
+ */
10
+ static VALUE private_iv_get(VALUE self, VALUE target, VALUE prop)
11
+ {
12
+ return rb_attr_get(target, rb_intern(StringValuePtr(prop)));
13
+ }
14
+
15
+ void Init_psych_yaml_tree(void)
16
+ {
17
+ VALUE psych = rb_define_module("Psych");
18
+ VALUE visitors = rb_define_module_under(psych, "Visitors");
19
+ VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject);
20
+ cPsychVisitorsYamlTree = rb_define_class_under(visitors, "YAMLTree", visitor);
21
+
22
+ rb_define_private_method(cPsychVisitorsYamlTree, "private_iv_get", private_iv_get, 2);
23
+ }
24
+ /* vim: set noet sws=4 sw=4: */
@@ -0,0 +1,8 @@
1
+ #ifndef PSYCH_YAML_TREE_H
2
+ #define PSYCH_YAML_TREE_H
3
+
4
+ #include <psych.h>
5
+
6
+ void Init_psych_yaml_tree(void);
7
+
8
+ #endif
data/lib/psych.rb ADDED
@@ -0,0 +1,263 @@
1
+ require 'psych.so'
2
+ require 'psych/nodes'
3
+ require 'psych/streaming'
4
+ require 'psych/visitors'
5
+ require 'psych/handler'
6
+ require 'psych/tree_builder'
7
+ require 'psych/parser'
8
+ require 'psych/omap'
9
+ require 'psych/set'
10
+ require 'psych/coder'
11
+ require 'psych/core_ext'
12
+ require 'psych/deprecated'
13
+ require 'psych/json'
14
+
15
+ ###
16
+ # = Overview
17
+ #
18
+ # Psych is a YAML parser and emitter. Psych leverages
19
+ # libyaml[http://libyaml.org] for it's YAML parsing and emitting capabilities.
20
+ # In addition to wrapping libyaml, Psych also knows how to serialize and
21
+ # de-serialize most Ruby objects to and from the YAML format.
22
+ #
23
+ # = I NEED TO PARSE OR EMIT YAML RIGHT NOW!
24
+ #
25
+ # # Parse some YAML
26
+ # Psych.load("--- foo") # => "foo"
27
+ #
28
+ # # Emit some YAML
29
+ # Psych.dump("foo") # => "--- foo\n...\n"
30
+ # { :a => 'b'}.to_yaml # => "---\n:a: b\n"
31
+ #
32
+ # Got more time on your hands? Keep on reading!
33
+ #
34
+ # == YAML Parsing
35
+ #
36
+ # Psych provides a range of interfaces for parsing a YAML document ranging from
37
+ # low level to high level, depending on your parsing needs. At the lowest
38
+ # level, is an event based parser. Mid level is access to the raw YAML AST,
39
+ # and at the highest level is the ability to unmarshal YAML to ruby objects.
40
+ #
41
+ # === Low level parsing
42
+ #
43
+ # The lowest level parser should be used when the YAML input is already known,
44
+ # and the developer does not want to pay the price of building an AST or
45
+ # automatic detection and conversion to ruby objects. See Psych::Parser for
46
+ # more information on using the event based parser.
47
+ #
48
+ # === Mid level parsing
49
+ #
50
+ # Psych provides access to an AST produced from parsing a YAML document. This
51
+ # tree is built using the Psych::Parser and Psych::TreeBuilder. The AST can
52
+ # be examined and manipulated freely. Please see Psych::parse_stream,
53
+ # Psych::Nodes, and Psych::Nodes::Node for more information on dealing with
54
+ # YAML syntax trees.
55
+ #
56
+ # === High level parsing
57
+ #
58
+ # The high level YAML parser provided by Psych simply takes YAML as input and
59
+ # returns a Ruby data structure. For information on using the high level parser
60
+ # see Psych.load
61
+ #
62
+ # == YAML Emitting
63
+ #
64
+ # Psych provides a range of interfaces ranging from low to high level for
65
+ # producing YAML documents. Very similar to the YAML parsing interfaces, Psych
66
+ # provides at the lowest level, an event based system, mid-level is building
67
+ # a YAML AST, and the highest level is converting a Ruby object straight to
68
+ # a YAML document.
69
+ #
70
+ # === Low level emitting
71
+ #
72
+ # The lowest level emitter is an event based system. Events are sent to a
73
+ # Psych::Emitter object. That object knows how to convert the events to a YAML
74
+ # document. This interface should be used when document format is known in
75
+ # advance or speed is a concern. See Psych::Emitter for more information.
76
+ #
77
+ # === Mid level emitting
78
+ #
79
+ # At the mid level is building an AST. This AST is exactly the same as the AST
80
+ # used when parsing a YAML document. Users can build an AST by hand and the
81
+ # AST knows how to emit itself as a YAML document. See Psych::Nodes,
82
+ # Psych::Nodes::Node, and Psych::TreeBuilder for more information on building
83
+ # a YAML AST.
84
+ #
85
+ # === High level emitting
86
+ #
87
+ # The high level emitter has the easiest interface. Psych simply takes a Ruby
88
+ # data structure and converts it to a YAML document. See Psych.dump for more
89
+ # information on dumping a Ruby data structure.
90
+
91
+ module Psych
92
+ # The version is Psych you're using
93
+ VERSION = '1.1.0'
94
+
95
+ # The version of libyaml Psych is using
96
+ LIBYAML_VERSION = Psych.libyaml_version.join '.'
97
+
98
+ class Exception < RuntimeError
99
+ end
100
+
101
+ autoload :Stream, 'psych/stream'
102
+
103
+ ###
104
+ # Load +yaml+ in to a Ruby data structure. If multiple documents are
105
+ # provided, the object contained in the first document will be returned.
106
+ #
107
+ # Example:
108
+ #
109
+ # Psych.load("--- a") # => 'a'
110
+ # Psych.load("---\n - a\n - b") # => ['a', 'b']
111
+ def self.load yaml
112
+ result = parse(yaml)
113
+ result ? result.to_ruby : result
114
+ end
115
+
116
+ ###
117
+ # Parse a YAML string in +yaml+. Returns the first object of a YAML AST.
118
+ #
119
+ # Example:
120
+ #
121
+ # Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Sequence:0x00>
122
+ #
123
+ # See Psych::Nodes for more information about YAML AST.
124
+ def self.parse yaml
125
+ children = parse_stream(yaml).children
126
+ children.empty? ? false : children.first.children.first
127
+ end
128
+
129
+ ###
130
+ # Parse a file at +filename+. Returns the YAML AST.
131
+ def self.parse_file filename
132
+ File.open filename do |f|
133
+ parse f
134
+ end
135
+ end
136
+
137
+ ###
138
+ # Returns a default parser
139
+ def self.parser
140
+ Psych::Parser.new(TreeBuilder.new)
141
+ end
142
+
143
+ ###
144
+ # Parse a YAML string in +yaml+. Returns the full AST for the YAML document.
145
+ # This method can handle multiple YAML documents contained in +yaml+.
146
+ #
147
+ # Example:
148
+ #
149
+ # Psych.parse_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
150
+ #
151
+ # See Psych::Nodes for more information about YAML AST.
152
+ def self.parse_stream yaml
153
+ parser = self.parser
154
+ parser.parse yaml
155
+ parser.handler.root
156
+ end
157
+
158
+ ###
159
+ # call-seq:
160
+ # Psych.dump(o) -> string of yaml
161
+ # Psych.dump(o, options) -> string of yaml
162
+ # Psych.dump(o, io) -> io object passed in
163
+ # Psych.dump(o, io, options) -> io object passed in
164
+ #
165
+ # Dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in
166
+ # to control the output format. If an IO object is passed in, the YAML will
167
+ # be dumped to that IO object.
168
+ #
169
+ # Example:
170
+ #
171
+ # # Dump an array, get back a YAML string
172
+ # Psych.dump(['a', 'b']) # => "---\n- a\n- b\n"
173
+ #
174
+ # # Dump an array to an IO object
175
+ # Psych.dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890>
176
+ #
177
+ # # Dump an array with indentation set
178
+ # Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n"
179
+ #
180
+ # # Dump an array to an IO with indentation set
181
+ # Psych.dump(['a', ['b']], StringIO.new, :indentation => 3)
182
+ def self.dump o, io = nil, options = {}
183
+ if Hash === io
184
+ options = io
185
+ io = nil
186
+ end
187
+
188
+ visitor = Psych::Visitors::YAMLTree.new options
189
+ visitor << o
190
+ visitor.tree.to_yaml io, options
191
+ end
192
+
193
+ ###
194
+ # Dump a list of objects as separate documents to a document stream.
195
+ #
196
+ # Example:
197
+ #
198
+ # Psych.dump_stream("foo\n ", {}) # => "--- ! \"foo\\n \"\n--- {}\n"
199
+ def self.dump_stream *objects
200
+ visitor = Psych::Visitors::YAMLTree.new {}
201
+ objects.each do |o|
202
+ visitor << o
203
+ end
204
+ visitor.tree.to_yaml
205
+ end
206
+
207
+ ###
208
+ # Dump Ruby object +o+ to a JSON string.
209
+ def self.to_json o
210
+ visitor = Psych::Visitors::JSONTree.new
211
+ visitor << o
212
+ visitor.tree.to_yaml
213
+ end
214
+
215
+ ###
216
+ # Load multiple documents given in +yaml+. Returns the parsed documents
217
+ # as a list. For example:
218
+ #
219
+ # Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
220
+ #
221
+ def self.load_stream yaml
222
+ parse_stream(yaml).children.map { |child| child.to_ruby }
223
+ end
224
+
225
+ ###
226
+ # Load the document contained in +filename+. Returns the yaml contained in
227
+ # +filename+ as a ruby object
228
+ def self.load_file filename
229
+ self.load File.open(filename)
230
+ end
231
+
232
+ # :stopdoc:
233
+ @domain_types = {}
234
+ def self.add_domain_type domain, type_tag, &block
235
+ key = ['tag', domain, type_tag].join ':'
236
+ @domain_types[key] = [key, block]
237
+ @domain_types["tag:#{type_tag}"] = [key, block]
238
+ end
239
+
240
+ def self.add_builtin_type type_tag, &block
241
+ domain = 'yaml.org,2002'
242
+ key = ['tag', domain, type_tag].join ':'
243
+ @domain_types[key] = [key, block]
244
+ end
245
+
246
+ def self.remove_type type_tag
247
+ @domain_types.delete type_tag
248
+ end
249
+
250
+ @load_tags = {}
251
+ @dump_tags = {}
252
+ def self.add_tag tag, klass
253
+ @load_tags[tag] = klass
254
+ @dump_tags[klass] = tag
255
+ end
256
+
257
+ class << self
258
+ attr_accessor :load_tags
259
+ attr_accessor :dump_tags
260
+ attr_accessor :domain_types
261
+ end
262
+ # :startdoc:
263
+ end
@@ -0,0 +1,94 @@
1
+ module Psych
2
+ ###
3
+ # If an object defines +encode_with+, then an instance of Psych::Coder will
4
+ # be passed to the method when the object is being serialized. The Coder
5
+ # automatically assumes a Psych::Nodes::Mapping is being emitted. Other
6
+ # objects like Sequence and Scalar may be emitted if +seq=+ or +scalar=+ are
7
+ # called, respectively.
8
+ class Coder
9
+ attr_accessor :tag, :style, :implicit, :object
10
+ attr_reader :type, :seq
11
+
12
+ def initialize tag
13
+ @map = {}
14
+ @seq = []
15
+ @implicit = false
16
+ @type = :map
17
+ @tag = tag
18
+ @style = Psych::Nodes::Mapping::BLOCK
19
+ @scalar = nil
20
+ @object = nil
21
+ end
22
+
23
+ def scalar *args
24
+ if args.length > 0
25
+ warn "#{caller[0]}: Coder#scalar(a,b,c) is deprecated" if $VERBOSE
26
+ @tag, @scalar, _ = args
27
+ @type = :scalar
28
+ end
29
+ @scalar
30
+ end
31
+
32
+ # Emit a map. The coder will be yielded to the block.
33
+ def map tag = @tag, style = @style
34
+ @tag = tag
35
+ @style = style
36
+ yield self if block_given?
37
+ @map
38
+ end
39
+
40
+ # Emit a scalar with +value+ and +tag+
41
+ def represent_scalar tag, value
42
+ self.tag = tag
43
+ self.scalar = value
44
+ end
45
+
46
+ # Emit a sequence with +list+ and +tag+
47
+ def represent_seq tag, list
48
+ @tag = tag
49
+ self.seq = list
50
+ end
51
+
52
+ # Emit a sequence with +map+ and +tag+
53
+ def represent_map tag, map
54
+ @tag = tag
55
+ self.map = map
56
+ end
57
+
58
+ # Emit an arbitrary object +obj+ and +tag+
59
+ def represent_object tag, obj
60
+ @tag = tag
61
+ @type = :object
62
+ @object = obj
63
+ end
64
+
65
+ # Emit a scalar with +value+
66
+ def scalar= value
67
+ @type = :scalar
68
+ @scalar = value
69
+ end
70
+
71
+ # Emit a map with +value+
72
+ def map= map
73
+ @type = :map
74
+ @map = map
75
+ end
76
+
77
+ def []= k, v
78
+ @type = :map
79
+ @map[k] = v
80
+ end
81
+ alias :add :[]=
82
+
83
+ def [] k
84
+ @type = :map
85
+ @map[k]
86
+ end
87
+
88
+ # Emit a sequence of +list+
89
+ def seq= list
90
+ @type = :seq
91
+ @seq = list
92
+ end
93
+ end
94
+ end