psych 4.0.0-java → 4.0.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/java/org/jruby/ext/psych/PsychEmitter.java +77 -33
- data/ext/java/org/jruby/ext/psych/PsychParser.java +65 -19
- data/lib/psych.rb +86 -3
- data/lib/psych/class_loader.rb +2 -2
- data/lib/psych/exception.rb +2 -2
- data/lib/psych/versions.rb +1 -1
- data/lib/psych/visitors/yaml_tree.rb +46 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23dccf627759f7113d2058885273d84aa92edc9a162a7a620510d27ba4c80fff
|
4
|
+
data.tar.gz: 50bd2d6eb02c3ea703bbb1064493c62ba7f579fdefa8b98cdb7a417438c5fd09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4bf4b8036cc63a7dffa4a0e0858a3eb327f1812d422c60c22852458f4a163dad53688c8bbef8300059c25ba61be455a470d5ca5918308648c450bde29231a5a
|
7
|
+
data.tar.gz: eba85f35d6f01299dd169c9c5e97f63ab795f041fa8e333a1dc26bfea125dbe14cb094b68535c687663210fc4dca88516babcd89f9235af68b493c42408f8a7d
|
@@ -29,13 +29,16 @@ package org.jruby.ext.psych;
|
|
29
29
|
|
30
30
|
import java.io.IOException;
|
31
31
|
import java.io.OutputStreamWriter;
|
32
|
+
import java.io.Writer;
|
32
33
|
import java.nio.charset.Charset;
|
33
34
|
import java.util.HashMap;
|
34
35
|
import java.util.Map;
|
35
36
|
|
36
37
|
import org.jcodings.Encoding;
|
38
|
+
import org.jcodings.specific.UTF8Encoding;
|
37
39
|
import org.jruby.Ruby;
|
38
40
|
import org.jruby.RubyArray;
|
41
|
+
import org.jruby.RubyBoolean;
|
39
42
|
import org.jruby.RubyClass;
|
40
43
|
import org.jruby.RubyFixnum;
|
41
44
|
import org.jruby.RubyModule;
|
@@ -46,6 +49,8 @@ import org.jruby.runtime.ObjectAllocator;
|
|
46
49
|
import org.jruby.runtime.ThreadContext;
|
47
50
|
import org.jruby.runtime.builtin.IRubyObject;
|
48
51
|
import org.jruby.util.IOOutputStream;
|
52
|
+
import org.jruby.util.TypeConverter;
|
53
|
+
import org.jruby.util.io.EncodingUtils;
|
49
54
|
import org.yaml.snakeyaml.DumperOptions;
|
50
55
|
import org.yaml.snakeyaml.emitter.Emitter;
|
51
56
|
import org.yaml.snakeyaml.emitter.EmitterException;
|
@@ -110,9 +115,7 @@ public class PsychEmitter extends RubyObject {
|
|
110
115
|
|
111
116
|
@JRubyMethod
|
112
117
|
public IRubyObject start_stream(ThreadContext context, IRubyObject encoding) {
|
113
|
-
|
114
|
-
throw context.runtime.newTypeError(encoding, context.runtime.getFixnum());
|
115
|
-
}
|
118
|
+
TypeConverter.checkType(context, encoding, context.runtime.getFixnum());
|
116
119
|
|
117
120
|
initEmitter(context, encoding);
|
118
121
|
|
@@ -136,6 +139,8 @@ public class PsychEmitter extends RubyObject {
|
|
136
139
|
boolean implicitBool = implicit.isTrue();
|
137
140
|
Map<String, String> tagsMap = null;
|
138
141
|
|
142
|
+
TypeConverter.checkType(context, _version, context.runtime.getArray());
|
143
|
+
|
139
144
|
RubyArray versionAry = _version.convertToArray();
|
140
145
|
if (versionAry.size() == 2) {
|
141
146
|
int versionInt0 = (int)versionAry.eltInternal(0).convertToInteger().getLongValue();
|
@@ -153,19 +158,23 @@ public class PsychEmitter extends RubyObject {
|
|
153
158
|
}
|
154
159
|
}
|
155
160
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
161
|
+
if (!tags.isNil()) {
|
162
|
+
TypeConverter.checkType(context, tags, context.runtime.getArray());
|
163
|
+
|
164
|
+
RubyArray tagsAry = tags.convertToArray();
|
165
|
+
if (tagsAry.size() > 0) {
|
166
|
+
tagsMap = new HashMap<>(tagsAry.size());
|
167
|
+
for (int i = 0; i < tagsAry.size(); i++) {
|
168
|
+
RubyArray tagsTuple = tagsAry.eltInternal(i).convertToArray();
|
169
|
+
if (tagsTuple.size() != 2) {
|
170
|
+
throw context.runtime.newRuntimeError("tags tuple must be of length 2");
|
171
|
+
}
|
172
|
+
IRubyObject key = tagsTuple.eltInternal(0);
|
173
|
+
IRubyObject value = tagsTuple.eltInternal(1);
|
174
|
+
tagsMap.put(
|
175
|
+
key.asJavaString(),
|
176
|
+
value.asJavaString());
|
163
177
|
}
|
164
|
-
IRubyObject key = tagsTuple.eltInternal(0);
|
165
|
-
IRubyObject value = tagsTuple.eltInternal(1);
|
166
|
-
tagsMap.put(
|
167
|
-
key.asJavaString(),
|
168
|
-
value.asJavaString());
|
169
178
|
}
|
170
179
|
}
|
171
180
|
|
@@ -189,21 +198,29 @@ public class PsychEmitter extends RubyObject {
|
|
189
198
|
IRubyObject plain = args[3];
|
190
199
|
IRubyObject quoted = args[4];
|
191
200
|
IRubyObject style = args[5];
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
201
|
+
|
202
|
+
RubyClass stringClass = context.runtime.getString();
|
203
|
+
|
204
|
+
TypeConverter.checkType(context, value, stringClass);
|
205
|
+
|
206
|
+
RubyString valueStr = (RubyString) value;
|
207
|
+
|
208
|
+
valueStr = EncodingUtils.strConvEnc(context, valueStr, valueStr.getEncoding(), UTF8Encoding.INSTANCE);
|
209
|
+
|
210
|
+
RubyString anchorStr = exportToUTF8(context, anchor, stringClass);
|
211
|
+
RubyString tagStr = exportToUTF8(context, tag, stringClass);
|
196
212
|
|
197
213
|
ScalarEvent event = new ScalarEvent(
|
198
|
-
|
199
|
-
|
200
|
-
new ImplicitTuple(plain.isTrue(),
|
201
|
-
|
202
|
-
value.asJavaString(),
|
214
|
+
anchorStr == null ? null : anchorStr.asJavaString(),
|
215
|
+
tagStr == null ? null : tagStr.asJavaString(),
|
216
|
+
new ImplicitTuple(plain.isTrue(), quoted.isTrue()),
|
217
|
+
valueStr.asJavaString(),
|
203
218
|
NULL_MARK,
|
204
219
|
NULL_MARK,
|
205
220
|
SCALAR_STYLES[style.convertToInteger().getIntValue()]);
|
221
|
+
|
206
222
|
emit(context, event);
|
223
|
+
|
207
224
|
return this;
|
208
225
|
}
|
209
226
|
|
@@ -214,11 +231,14 @@ public class PsychEmitter extends RubyObject {
|
|
214
231
|
IRubyObject implicit = args[2];
|
215
232
|
IRubyObject style = args[3];
|
216
233
|
|
217
|
-
|
234
|
+
RubyClass stringClass = context.runtime.getString();
|
235
|
+
|
236
|
+
RubyString anchorStr = exportToUTF8(context, anchor, stringClass);
|
237
|
+
RubyString tagStr = exportToUTF8(context, tag, stringClass);
|
218
238
|
|
219
239
|
SequenceStartEvent event = new SequenceStartEvent(
|
220
|
-
|
221
|
-
|
240
|
+
anchorStr == null ? null : anchorStr.asJavaString(),
|
241
|
+
tagStr == null ? null : tagStr.asJavaString(),
|
222
242
|
implicit.isTrue(),
|
223
243
|
NULL_MARK,
|
224
244
|
NULL_MARK,
|
@@ -241,16 +261,21 @@ public class PsychEmitter extends RubyObject {
|
|
241
261
|
IRubyObject implicit = args[2];
|
242
262
|
IRubyObject style = args[3];
|
243
263
|
|
244
|
-
|
264
|
+
RubyClass stringClass = context.runtime.getString();
|
265
|
+
|
266
|
+
RubyString anchorStr = exportToUTF8(context, anchor, stringClass);
|
267
|
+
RubyString tagStr = exportToUTF8(context, tag, stringClass);
|
245
268
|
|
246
269
|
MappingStartEvent event = new MappingStartEvent(
|
247
|
-
|
248
|
-
|
270
|
+
anchorStr == null ? null : anchorStr.asJavaString(),
|
271
|
+
tagStr == null ? null : tagStr.asJavaString(),
|
249
272
|
implicit.isTrue(),
|
250
273
|
NULL_MARK,
|
251
274
|
NULL_MARK,
|
252
275
|
FLOW_STYLES[style.convertToInteger().getIntValue()]);
|
276
|
+
|
253
277
|
emit(context, event);
|
278
|
+
|
254
279
|
return this;
|
255
280
|
}
|
256
281
|
|
@@ -263,7 +288,11 @@ public class PsychEmitter extends RubyObject {
|
|
263
288
|
|
264
289
|
@JRubyMethod
|
265
290
|
public IRubyObject alias(ThreadContext context, IRubyObject anchor) {
|
266
|
-
|
291
|
+
RubyClass stringClass = context.runtime.getString();
|
292
|
+
|
293
|
+
RubyString anchorStr = exportToUTF8(context, anchor, stringClass);
|
294
|
+
|
295
|
+
AliasEvent event = new AliasEvent(anchorStr.asJavaString(), NULL_MARK, NULL_MARK);
|
267
296
|
emit(context, event);
|
268
297
|
return this;
|
269
298
|
}
|
@@ -278,7 +307,7 @@ public class PsychEmitter extends RubyObject {
|
|
278
307
|
@JRubyMethod
|
279
308
|
public IRubyObject canonical(ThreadContext context) {
|
280
309
|
// TODO: unclear if this affects a running emitter
|
281
|
-
return
|
310
|
+
return RubyBoolean.newBoolean(context, options.isCanonical());
|
282
311
|
}
|
283
312
|
|
284
313
|
@JRubyMethod(name = "indentation=")
|
@@ -312,6 +341,9 @@ public class PsychEmitter extends RubyObject {
|
|
312
341
|
if (emitter == null) throw context.runtime.newRuntimeError("uninitialized emitter");
|
313
342
|
|
314
343
|
emitter.emit(event);
|
344
|
+
|
345
|
+
// flush writer after each emit
|
346
|
+
writer.flush();
|
315
347
|
} catch (IOException ioe) {
|
316
348
|
throw context.runtime.newIOErrorFromException(ioe);
|
317
349
|
} catch (EmitterException ee) {
|
@@ -325,10 +357,22 @@ public class PsychEmitter extends RubyObject {
|
|
325
357
|
Encoding encoding = PsychLibrary.YAMLEncoding.values()[(int)_encoding.convertToInteger().getLongValue()].encoding;
|
326
358
|
Charset charset = context.runtime.getEncodingService().charsetForEncoding(encoding);
|
327
359
|
|
328
|
-
|
360
|
+
writer = new OutputStreamWriter(new IOOutputStream(io, encoding), charset);
|
361
|
+
emitter = new Emitter(writer, options);
|
362
|
+
}
|
363
|
+
|
364
|
+
private RubyString exportToUTF8(ThreadContext context, IRubyObject tag, RubyClass stringClass) {
|
365
|
+
RubyString tagStr = null;
|
366
|
+
if (!tag.isNil()) {
|
367
|
+
TypeConverter.checkType(context, tag, stringClass);
|
368
|
+
tagStr = (RubyString) tag;
|
369
|
+
tagStr = EncodingUtils.strConvEnc(context, tagStr, tagStr.getEncoding(), UTF8Encoding.INSTANCE);
|
370
|
+
}
|
371
|
+
return tagStr;
|
329
372
|
}
|
330
373
|
|
331
374
|
Emitter emitter;
|
375
|
+
Writer writer;
|
332
376
|
DumperOptions options = new DumperOptions();
|
333
377
|
IRubyObject io;
|
334
378
|
|
@@ -30,6 +30,9 @@ package org.jruby.ext.psych;
|
|
30
30
|
import java.io.ByteArrayInputStream;
|
31
31
|
import java.io.InputStreamReader;
|
32
32
|
import java.nio.charset.Charset;
|
33
|
+
import java.nio.charset.CharsetDecoder;
|
34
|
+
import java.nio.charset.CodingErrorAction;
|
35
|
+
import java.nio.charset.MalformedInputException;
|
33
36
|
import java.util.Map;
|
34
37
|
|
35
38
|
import org.jcodings.Encoding;
|
@@ -61,6 +64,7 @@ import org.jruby.util.log.LoggerFactory;
|
|
61
64
|
import org.yaml.snakeyaml.DumperOptions;
|
62
65
|
import org.yaml.snakeyaml.error.Mark;
|
63
66
|
import org.yaml.snakeyaml.error.MarkedYAMLException;
|
67
|
+
import org.yaml.snakeyaml.error.YAMLException;
|
64
68
|
import org.yaml.snakeyaml.events.AliasEvent;
|
65
69
|
import org.yaml.snakeyaml.events.DocumentEndEvent;
|
66
70
|
import org.yaml.snakeyaml.events.DocumentStartEvent;
|
@@ -75,6 +79,8 @@ import org.yaml.snakeyaml.parser.ParserImpl;
|
|
75
79
|
import org.yaml.snakeyaml.reader.ReaderException;
|
76
80
|
import org.yaml.snakeyaml.reader.StreamReader;
|
77
81
|
import org.yaml.snakeyaml.scanner.ScannerException;
|
82
|
+
|
83
|
+
import static org.jruby.runtime.Helpers.arrayOf;
|
78
84
|
import static org.jruby.runtime.Helpers.invoke;
|
79
85
|
import org.jruby.util.ByteList;
|
80
86
|
|
@@ -89,8 +95,7 @@ public class PsychParser extends RubyObject {
|
|
89
95
|
}
|
90
96
|
}, psych);
|
91
97
|
|
92
|
-
|
93
|
-
runtime.newString("psych/syntax_error"), Block.NULL_BLOCK);
|
98
|
+
runtime.getLoadService().require("psych/syntax_error");
|
94
99
|
psychParser.defineConstant("ANY", runtime.newFixnum(YAML_ANY_ENCODING.ordinal()));
|
95
100
|
psychParser.defineConstant("UTF8", runtime.newFixnum(YAML_UTF8_ENCODING.ordinal()));
|
96
101
|
psychParser.defineConstant("UTF16LE", runtime.newFixnum(YAML_UTF16LE_ENCODING.ordinal()));
|
@@ -110,13 +115,15 @@ public class PsychParser extends RubyObject {
|
|
110
115
|
return parse(context, yaml, runtime.getNil());
|
111
116
|
}
|
112
117
|
|
113
|
-
private IRubyObject stringOrNilFor(
|
114
|
-
if (value == null) return
|
118
|
+
private IRubyObject stringOrNilFor(ThreadContext context, String value, boolean tainted) {
|
119
|
+
if (value == null) return context.nil;
|
115
120
|
|
116
|
-
return stringFor(
|
121
|
+
return stringFor(context, value, tainted);
|
117
122
|
}
|
118
123
|
|
119
|
-
private RubyString stringFor(
|
124
|
+
private RubyString stringFor(ThreadContext context, String value, boolean tainted) {
|
125
|
+
Ruby runtime = context.runtime;
|
126
|
+
|
120
127
|
Encoding encoding = runtime.getDefaultInternalEncoding();
|
121
128
|
if (encoding == null) {
|
122
129
|
encoding = UTF8Encoding.INSTANCE;
|
@@ -136,8 +143,6 @@ public class PsychParser extends RubyObject {
|
|
136
143
|
}
|
137
144
|
|
138
145
|
private StreamReader readerFor(ThreadContext context, IRubyObject yaml) {
|
139
|
-
Ruby runtime = context.runtime;
|
140
|
-
|
141
146
|
if (yaml instanceof RubyString) {
|
142
147
|
ByteList byteList = ((RubyString)yaml).getByteList();
|
143
148
|
Encoding enc = byteList.getEncoding();
|
@@ -175,8 +180,14 @@ public class PsychParser extends RubyObject {
|
|
175
180
|
// If we can't get it from the IO or it doesn't have a charset, fall back on UTF-8
|
176
181
|
charset = UTF8Encoding.INSTANCE.getCharset();
|
177
182
|
}
|
178
|
-
|
183
|
+
CharsetDecoder decoder = charset.newDecoder();
|
184
|
+
decoder.onMalformedInput(CodingErrorAction.REPORT);
|
185
|
+
decoder.onMalformedInput(CodingErrorAction.REPORT);
|
186
|
+
|
187
|
+
return new StreamReader(new InputStreamReader(new IOInputStream(yaml), decoder));
|
179
188
|
} else {
|
189
|
+
Ruby runtime = context.runtime;
|
190
|
+
|
180
191
|
throw runtime.newTypeError(yaml, runtime.getIO());
|
181
192
|
}
|
182
193
|
}
|
@@ -214,7 +225,7 @@ public class PsychParser extends RubyObject {
|
|
214
225
|
|
215
226
|
invoke(context, handler, "end_document", notExplicit);
|
216
227
|
} else if (event.is(ID.Alias)) {
|
217
|
-
IRubyObject alias = stringOrNilFor(
|
228
|
+
IRubyObject alias = stringOrNilFor(context, ((AliasEvent)event).getAnchor(), tainted);
|
218
229
|
|
219
230
|
invoke(context, handler, "alias", alias);
|
220
231
|
} else if (event.is(ID.Scalar)) {
|
@@ -249,6 +260,16 @@ public class PsychParser extends RubyObject {
|
|
249
260
|
parser = null;
|
250
261
|
raiseParserException(context, yaml, re, path);
|
251
262
|
|
263
|
+
} catch (YAMLException ye) {
|
264
|
+
Throwable cause = ye.getCause();
|
265
|
+
|
266
|
+
if (cause instanceof MalformedInputException) {
|
267
|
+
// failure due to improperly encoded input
|
268
|
+
raiseParserException(context, yaml, (MalformedInputException) cause, path);
|
269
|
+
}
|
270
|
+
|
271
|
+
throw ye;
|
272
|
+
|
252
273
|
} catch (Throwable t) {
|
253
274
|
Helpers.throwException(t);
|
254
275
|
return this;
|
@@ -268,8 +289,8 @@ public class PsychParser extends RubyObject {
|
|
268
289
|
RubyArray tags = RubyArray.newArray(runtime);
|
269
290
|
if (tagsMap != null && tagsMap.size() > 0) {
|
270
291
|
for (Map.Entry<String, String> tag : tagsMap.entrySet()) {
|
271
|
-
IRubyObject key = stringFor(
|
272
|
-
IRubyObject value = stringFor(
|
292
|
+
IRubyObject key = stringFor(context, tag.getKey(), tainted);
|
293
|
+
IRubyObject value = stringFor(context, tag.getValue(), tainted);
|
273
294
|
|
274
295
|
tags.append(RubyArray.newArray(runtime, key, value));
|
275
296
|
}
|
@@ -281,8 +302,8 @@ public class PsychParser extends RubyObject {
|
|
281
302
|
|
282
303
|
private void handleMappingStart(ThreadContext context, MappingStartEvent mse, boolean tainted, IRubyObject handler) {
|
283
304
|
Ruby runtime = context.runtime;
|
284
|
-
IRubyObject anchor = stringOrNilFor(
|
285
|
-
IRubyObject tag = stringOrNilFor(
|
305
|
+
IRubyObject anchor = stringOrNilFor(context, mse.getAnchor(), tainted);
|
306
|
+
IRubyObject tag = stringOrNilFor(context, mse.getTag(), tainted);
|
286
307
|
IRubyObject implicit = runtime.newBoolean(mse.getImplicit());
|
287
308
|
IRubyObject style = runtime.newFixnum(translateFlowStyle(mse.getFlowStyle()));
|
288
309
|
|
@@ -292,12 +313,12 @@ public class PsychParser extends RubyObject {
|
|
292
313
|
private void handleScalar(ThreadContext context, ScalarEvent se, boolean tainted, IRubyObject handler) {
|
293
314
|
Ruby runtime = context.runtime;
|
294
315
|
|
295
|
-
IRubyObject anchor = stringOrNilFor(
|
296
|
-
IRubyObject tag = stringOrNilFor(
|
316
|
+
IRubyObject anchor = stringOrNilFor(context, se.getAnchor(), tainted);
|
317
|
+
IRubyObject tag = stringOrNilFor(context, se.getTag(), tainted);
|
297
318
|
IRubyObject plain_implicit = runtime.newBoolean(se.getImplicit().canOmitTagInPlainScalar());
|
298
319
|
IRubyObject quoted_implicit = runtime.newBoolean(se.getImplicit().canOmitTagInNonPlainScalar());
|
299
320
|
IRubyObject style = runtime.newFixnum(translateStyle(se.getScalarStyle()));
|
300
|
-
IRubyObject val = stringFor(
|
321
|
+
IRubyObject val = stringFor(context, se.getValue(), tainted);
|
301
322
|
|
302
323
|
invoke(context, handler, "scalar", val, anchor, tag, plain_implicit,
|
303
324
|
quoted_implicit, style);
|
@@ -305,8 +326,8 @@ public class PsychParser extends RubyObject {
|
|
305
326
|
|
306
327
|
private void handleSequenceStart(ThreadContext context, SequenceStartEvent sse, boolean tainted, IRubyObject handler) {
|
307
328
|
Ruby runtime = context.runtime;
|
308
|
-
IRubyObject anchor = stringOrNilFor(
|
309
|
-
IRubyObject tag = stringOrNilFor(
|
329
|
+
IRubyObject anchor = stringOrNilFor(context, sse.getAnchor(), tainted);
|
330
|
+
IRubyObject tag = stringOrNilFor(context, sse.getTag(), tainted);
|
310
331
|
IRubyObject implicit = runtime.newBoolean(sse.getImplicit());
|
311
332
|
IRubyObject style = runtime.newFixnum(translateFlowStyle(sse.getFlowStyle()));
|
312
333
|
|
@@ -360,6 +381,31 @@ public class PsychParser extends RubyObject {
|
|
360
381
|
RubyKernel.raise(context, runtime.getKernel(), new IRubyObject[] { exception }, Block.NULL_BLOCK);
|
361
382
|
}
|
362
383
|
|
384
|
+
private static void raiseParserException(ThreadContext context, IRubyObject yaml, MalformedInputException mie, IRubyObject rbPath) {
|
385
|
+
Ruby runtime;
|
386
|
+
Mark mark;
|
387
|
+
RubyClass se;
|
388
|
+
IRubyObject exception;
|
389
|
+
|
390
|
+
runtime = context.runtime;
|
391
|
+
se = (RubyClass)runtime.getModule("Psych").getConstant("SyntaxError");
|
392
|
+
|
393
|
+
mie.getInputLength();
|
394
|
+
|
395
|
+
exception = se.newInstance(context,
|
396
|
+
arrayOf(
|
397
|
+
rbPath,
|
398
|
+
runtime.newFixnum(-1),
|
399
|
+
runtime.newFixnum(-1),
|
400
|
+
runtime.newFixnum(mie.getInputLength()),
|
401
|
+
runtime.getNil(),
|
402
|
+
runtime.getNil()
|
403
|
+
),
|
404
|
+
Block.NULL_BLOCK);
|
405
|
+
|
406
|
+
RubyKernel.raise(context, runtime.getKernel(), new IRubyObject[] { exception }, Block.NULL_BLOCK);
|
407
|
+
}
|
408
|
+
|
363
409
|
private static int translateStyle(DumperOptions.ScalarStyle style) {
|
364
410
|
if (style == null) return 0; // any
|
365
411
|
|
data/lib/psych.rb
CHANGED
@@ -282,7 +282,8 @@ module Psych
|
|
282
282
|
# * TrueClass
|
283
283
|
# * FalseClass
|
284
284
|
# * NilClass
|
285
|
-
# *
|
285
|
+
# * Integer
|
286
|
+
# * Float
|
286
287
|
# * String
|
287
288
|
# * Array
|
288
289
|
# * Hash
|
@@ -512,6 +513,79 @@ module Psych
|
|
512
513
|
visitor.tree.yaml io, options
|
513
514
|
end
|
514
515
|
|
516
|
+
###
|
517
|
+
# call-seq:
|
518
|
+
# Psych.safe_dump(o) -> string of yaml
|
519
|
+
# Psych.safe_dump(o, options) -> string of yaml
|
520
|
+
# Psych.safe_dump(o, io) -> io object passed in
|
521
|
+
# Psych.safe_dump(o, io, options) -> io object passed in
|
522
|
+
#
|
523
|
+
# Safely dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in
|
524
|
+
# to control the output format. If an IO object is passed in, the YAML will
|
525
|
+
# be dumped to that IO object. By default, only the following
|
526
|
+
# classes are allowed to be serialized:
|
527
|
+
#
|
528
|
+
# * TrueClass
|
529
|
+
# * FalseClass
|
530
|
+
# * NilClass
|
531
|
+
# * Integer
|
532
|
+
# * Float
|
533
|
+
# * String
|
534
|
+
# * Array
|
535
|
+
# * Hash
|
536
|
+
#
|
537
|
+
# Arbitrary classes can be allowed by adding those classes to the +permitted_classes+
|
538
|
+
# keyword argument. They are additive. For example, to allow Date serialization:
|
539
|
+
#
|
540
|
+
# Psych.safe_dump(yaml, permitted_classes: [Date])
|
541
|
+
#
|
542
|
+
# Now the Date class can be dumped in addition to the classes listed above.
|
543
|
+
#
|
544
|
+
# A Psych::DisallowedClass exception will be raised if the object contains a
|
545
|
+
# class that isn't in the +permitted_classes+ list.
|
546
|
+
#
|
547
|
+
# Currently supported options are:
|
548
|
+
#
|
549
|
+
# [<tt>:indentation</tt>] Number of space characters used to indent.
|
550
|
+
# Acceptable value should be in <tt>0..9</tt> range,
|
551
|
+
# otherwise option is ignored.
|
552
|
+
#
|
553
|
+
# Default: <tt>2</tt>.
|
554
|
+
# [<tt>:line_width</tt>] Max character to wrap line at.
|
555
|
+
#
|
556
|
+
# Default: <tt>0</tt> (meaning "wrap at 81").
|
557
|
+
# [<tt>:canonical</tt>] Write "canonical" YAML form (very verbose, yet
|
558
|
+
# strictly formal).
|
559
|
+
#
|
560
|
+
# Default: <tt>false</tt>.
|
561
|
+
# [<tt>:header</tt>] Write <tt>%YAML [version]</tt> at the beginning of document.
|
562
|
+
#
|
563
|
+
# Default: <tt>false</tt>.
|
564
|
+
#
|
565
|
+
# Example:
|
566
|
+
#
|
567
|
+
# # Dump an array, get back a YAML string
|
568
|
+
# Psych.safe_dump(['a', 'b']) # => "---\n- a\n- b\n"
|
569
|
+
#
|
570
|
+
# # Dump an array to an IO object
|
571
|
+
# Psych.safe_dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890>
|
572
|
+
#
|
573
|
+
# # Dump an array with indentation set
|
574
|
+
# Psych.safe_dump(['a', ['b']], indentation: 3) # => "---\n- a\n- - b\n"
|
575
|
+
#
|
576
|
+
# # Dump an array to an IO with indentation set
|
577
|
+
# Psych.safe_dump(['a', ['b']], StringIO.new, indentation: 3)
|
578
|
+
def self.safe_dump o, io = nil, options = {}
|
579
|
+
if Hash === io
|
580
|
+
options = io
|
581
|
+
io = nil
|
582
|
+
end
|
583
|
+
|
584
|
+
visitor = Psych::Visitors::RestrictedYAMLTree.create options
|
585
|
+
visitor << o
|
586
|
+
visitor.tree.yaml io, options
|
587
|
+
end
|
588
|
+
|
515
589
|
###
|
516
590
|
# Dump a list of objects as separate documents to a document stream.
|
517
591
|
#
|
@@ -575,7 +649,6 @@ module Psych
|
|
575
649
|
self.unsafe_load f, filename: filename, **kwargs
|
576
650
|
}
|
577
651
|
end
|
578
|
-
class << self; alias :load_file :unsafe_load_file; end
|
579
652
|
|
580
653
|
###
|
581
654
|
# Safely loads the document contained in +filename+. Returns the yaml contained in
|
@@ -587,7 +660,17 @@ module Psych
|
|
587
660
|
self.safe_load f, filename: filename, **kwargs
|
588
661
|
}
|
589
662
|
end
|
590
|
-
|
663
|
+
|
664
|
+
###
|
665
|
+
# Loads the document contained in +filename+. Returns the yaml contained in
|
666
|
+
# +filename+ as a Ruby object, or if the file is empty, it returns
|
667
|
+
# the specified +fallback+ return value, which defaults to +false+.
|
668
|
+
# See load for options.
|
669
|
+
def self.load_file filename, **kwargs
|
670
|
+
File.open(filename, 'r:bom|utf-8') { |f|
|
671
|
+
self.load f, filename: filename, **kwargs
|
672
|
+
}
|
673
|
+
end
|
591
674
|
|
592
675
|
# :stopdoc:
|
593
676
|
def self.add_domain_type domain, type_tag, &block
|
data/lib/psych/class_loader.rb
CHANGED
@@ -86,7 +86,7 @@ module Psych
|
|
86
86
|
if @symbols.include? sym
|
87
87
|
super
|
88
88
|
else
|
89
|
-
raise DisallowedClass, 'Symbol'
|
89
|
+
raise DisallowedClass.new('load', 'Symbol')
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
@@ -96,7 +96,7 @@ module Psych
|
|
96
96
|
if @classes.include? klassname
|
97
97
|
super
|
98
98
|
else
|
99
|
-
raise DisallowedClass, klassname
|
99
|
+
raise DisallowedClass.new('load', klassname)
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
data/lib/psych/exception.rb
CHANGED
@@ -7,8 +7,8 @@ module Psych
|
|
7
7
|
end
|
8
8
|
|
9
9
|
class DisallowedClass < Exception
|
10
|
-
def initialize klass_name
|
11
|
-
super "Tried to
|
10
|
+
def initialize action, klass_name
|
11
|
+
super "Tried to #{action} unspecified class: #{klass_name}"
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
data/lib/psych/versions.rb
CHANGED
@@ -535,5 +535,51 @@ module Psych
|
|
535
535
|
end
|
536
536
|
end
|
537
537
|
end
|
538
|
+
|
539
|
+
class RestrictedYAMLTree < YAMLTree
|
540
|
+
DEFAULT_PERMITTED_CLASSES = {
|
541
|
+
TrueClass => true,
|
542
|
+
FalseClass => true,
|
543
|
+
NilClass => true,
|
544
|
+
Integer => true,
|
545
|
+
Float => true,
|
546
|
+
String => true,
|
547
|
+
Array => true,
|
548
|
+
Hash => true,
|
549
|
+
}.compare_by_identity.freeze
|
550
|
+
|
551
|
+
def initialize emitter, ss, options
|
552
|
+
super
|
553
|
+
@permitted_classes = DEFAULT_PERMITTED_CLASSES.dup
|
554
|
+
Array(options[:permitted_classes]).each do |klass|
|
555
|
+
@permitted_classes[klass] = true
|
556
|
+
end
|
557
|
+
@permitted_symbols = {}.compare_by_identity
|
558
|
+
Array(options[:permitted_symbols]).each do |symbol|
|
559
|
+
@permitted_symbols[symbol] = true
|
560
|
+
end
|
561
|
+
@aliases = options.fetch(:aliases, false)
|
562
|
+
end
|
563
|
+
|
564
|
+
def accept target
|
565
|
+
if !@aliases && @st.key?(target)
|
566
|
+
raise BadAlias, "Tried to dump an aliased object"
|
567
|
+
end
|
568
|
+
|
569
|
+
unless @permitted_classes[target.class]
|
570
|
+
raise DisallowedClass.new('dump', target.class.name || target.class.inspect)
|
571
|
+
end
|
572
|
+
|
573
|
+
super
|
574
|
+
end
|
575
|
+
|
576
|
+
def visit_Symbol sym
|
577
|
+
unless @permitted_symbols[sym]
|
578
|
+
raise DisallowedClass.new('dump', "Symbol(#{sym.inspect})")
|
579
|
+
end
|
580
|
+
|
581
|
+
super
|
582
|
+
end
|
583
|
+
end
|
538
584
|
end
|
539
585
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: psych
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.1
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Aaron Patterson
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-
|
13
|
+
date: 2021-06-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -19,8 +19,8 @@ dependencies:
|
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: 0.1.7
|
21
21
|
name: jar-dependencies
|
22
|
-
type: :runtime
|
23
22
|
prerelease: false
|
23
|
+
type: :runtime
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - ">="
|
@@ -138,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
138
|
version: '0'
|
139
139
|
requirements:
|
140
140
|
- jar org.yaml:snakeyaml, 1.28
|
141
|
-
rubygems_version: 3.
|
141
|
+
rubygems_version: 3.1.6
|
142
142
|
signing_key:
|
143
143
|
specification_version: 4
|
144
144
|
summary: Psych is a YAML parser and emitter
|