yeptris 0.1.32.1 → 0.2.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 715a303c3798b0e446f0511093790dcc23958039cee970672772bf34d724614e
4
- data.tar.gz: fba78db515f493833a9c43c6931386c7cd4958582eda1f98b1e4ffef6dbfb950
3
+ metadata.gz: 1173c7a995c80564dbb7685e5b3a8e01ffce35233f5736367affa9b4cfc47fbf
4
+ data.tar.gz: 36facc6eda9fd872c00149122f7edadcf88909702317e5f34ff20cd4e202359d
5
5
  SHA512:
6
- metadata.gz: 3024caec31b6a0e1535e2dfcbe53c61aa790fca013a14a4138f266c12acc6016cd6ab53c83a0c1bb70f39ecddc717ed0eff83baf78613440fc150aed29e0ec54
7
- data.tar.gz: ce5a508e4efcd1485f4d18121025a203579c53d9b990246b2961991009e5c4367140eb993bdfe28ca380776dd95be4922d3fea0fa89146b439fbf5922c14cee3
6
+ metadata.gz: 720c5a7a2b1ebca34757c05b8fbaff07669797b0abf2758e37330beb86156c3d0a302848412d792912726f7b62dda9a56d0fb0fec57c2657d19c8ba10bfbf014
7
+ data.tar.gz: fc0e98a14c2c5ee6d88cbba2bce4ff097427f01be955ca138a16adf730ed37cb0b2279e12565707518dfd895ae9245c55add02128f59e31141fd8924154c30a3
data/README.adoc CHANGED
@@ -116,11 +116,26 @@ without compiling).
116
116
  (`Node#to_ruby` becomes bulk). Alias identity preserved through
117
117
  object links; merge keys and timestamps return UNSUPPORTED for the
118
118
  record-walk fallback.
119
- * `Yeptris::Psych` — the drop-in namespace with the ported Psych
120
- suite (143 specs), `.tml` corpora conformance, and the Encodable
121
- object protocol (`include Yeptris::Psych::Encodable` +
119
+ * `Yeptris::Psych` — the Psych-compatible namespace with the ported
120
+ Psych suite (143 specs), `.tml` corpora conformance, and the
121
+ Encodable object protocol (`include Yeptris::Psych::Encodable` +
122
122
  `encode_with`/`init_with` — no `respond_to?`, no ivar reflection;
123
123
  the library never reaches into an object's internals).
124
+ ** CO-EXISTENCE (issue #69): `require "yeptris/psych"` loads the
125
+ namespace WITHOUT touching the top-level `Psych` constant — it
126
+ coexists with stdlib psych in ANY load order. The process-
127
+ exclusive drop-in rebind (`::Psych = Yeptris::Psych`) is now
128
+ OPT-IN: `require "yeptris/psych/drop_in"`. Once the drop-in runs,
129
+ stdlib psych must NOT be loaded afterwards (its require re-opens
130
+ the rebound module and clobbers constants). Bundles that cannot
131
+ control the load order (activesupport et al.) should use
132
+ `Yeptris::Psych` / `Yeptris::YAML` directly.
133
+ ** `Yeptris::YAML.safe_load(yaml, permitted_classes: [], aliases:
134
+ false)` — Psych's safe_load semantics on the native surface:
135
+ plain data by default; a leaf that would materialize to a
136
+ non-permitted class (a compat_11 date) raises
137
+ `Yeptris::Psych::DisallowedClass`; alias use without `aliases:
138
+ true` raises `Yeptris::Psych::AliasesError`.
124
139
  * Lockstep versioning with the C library
125
140
  (`{c-semver}.{gem-patch}`); releases published from the C repo's
126
141
  workflow through the RubyGems trusted publisher.
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The process-exclusive drop-in (issue #69): rebinds the top-level
4
+ # Psych constant to Yeptris::Psych. Once this runs, stdlib psych must
5
+ # NOT be loaded afterwards — its require would re-open THIS module and
6
+ # clobber constants ("already initialized" warnings, then
7
+ # NameError/NoMethodError at call time). Bundles that cannot
8
+ # guarantee the load order (activesupport et al.) should require
9
+ # "yeptris/psych" only and reference Yeptris::Psych directly.
10
+ require "yeptris" # the autoload declarations (Document, Node, ...) live here
11
+ require "yeptris/psych"
12
+
13
+ # ( Psych-stdlib, if already loaded, stays reachable as
14
+ # ::Psych::ORIGINAL.)
15
+ if defined?(::Psych) && !::Psych.equal?(Yeptris::Psych) &&
16
+ !Yeptris::Psych.const_defined?(:ORIGINAL, false)
17
+ Yeptris::Psych.const_set(:ORIGINAL, ::Psych)
18
+ end
19
+ # class_eval reaches Module-private methods WITHOUT send (the law: no
20
+ # send to private methods); remove_const has no public form, and the
21
+ # rebind is this file's whole purpose
22
+ Object.class_eval { remove_const(:Psych) } if defined?(::Psych) && !::Psych.equal?(Yeptris::Psych)
23
+ ::Psych = Yeptris::Psych
data/lib/yeptris/psych.rb CHANGED
@@ -6,8 +6,10 @@ require "set"
6
6
 
7
7
  # The Psych drop-in namespace (TODO.impl/15 phase C).
8
8
  #
9
- # `require "yeptris/psych"` rebinds the top-level Psych constant to
10
- # this module (the original, if any, stays reachable as
9
+ # `require "yeptris/psych"` loads this namespace WITHOUT touching the
10
+ # top-level Psych constant (co-existence, issue #69); the process-
11
+ # exclusive drop-in rebind is `require "yeptris/psych/drop_in"` (the
12
+ # original stdlib, if loaded first, stays reachable as
11
13
  # ::Psych::ORIGINAL). Semantics follow the Psych suite: load is
12
14
  # SAFE by default (Psych 5 behavior — plain data only; anything
13
15
  # tagged raises), unsafe_load materializes everything the yeptris
@@ -65,7 +67,10 @@ module Yeptris
65
67
  @name = name
66
68
  end
67
69
  end
68
- class AliasNotEnabled < Error; end
70
+ # Psych spells it Psych::AliasesError; the older name stays as an
71
+ # alias for existing rescues.
72
+ class AliasesError < Error; end
73
+ AliasNotEnabled = AliasesError
69
74
 
70
75
  class << self
71
76
  # Psych 5: load is safe — plain data structures only. Tagged
@@ -146,19 +151,24 @@ module Yeptris
146
151
  private
147
152
 
148
153
  # yeptris materializes plain data only — there is nothing
149
- # unsafe it COULD load. The safety walk enforces what Psych
150
- # enforces on such documents: aliases need opt-in, and explicit
151
- # non-core tags raise DisallowedClass (the only "classes" the
152
- # loader can produce are core-schema types, all permitted).
154
+ # unsafe it COULD load. The safety walk enforces Psych's
155
+ # contract: aliases need opt-in, explicit non-core tags raise
156
+ # DisallowedClass, and a scalar whose IMPLICIT typing yields a
157
+ # class outside the permitted set raises too (issue #69: a
158
+ # compat_11 date must not become a Date unless Date is
159
+ # permitted — Psych::DisallowedClass semantics).
153
160
  def walk_safe(root, permitted, aliases_enabled)
154
- check(root, aliases_enabled) if root
161
+ check(root, permitted, aliases_enabled) if root
155
162
  root.to_ruby
156
163
  end
157
164
 
158
- def check(node, aliases_enabled)
165
+ PERMITTED_BY_DEFAULT = [TrueClass, FalseClass, NilClass, Integer, Float,
166
+ String, Array, Hash].freeze
167
+
168
+ def check(node, permitted, aliases_enabled)
159
169
  case node.kind
160
170
  when :alias
161
- raise AliasNotEnabled, "Unknown alias" unless aliases_enabled
171
+ raise AliasesError, "Unknown alias" unless aliases_enabled
162
172
  when :scalar, :mapping, :sequence
163
173
  tag = node.tag
164
174
  unless tag.nil?
@@ -168,14 +178,18 @@ module Yeptris
168
178
  raise DisallowedClass, name
169
179
  end
170
180
  end
181
+ if node.kind == :scalar && node.tag_id == :timestamp &&
182
+ !permitted.include?(Date) && !permitted.include?(Time)
183
+ raise DisallowedClass, "Date"
184
+ end
171
185
  case node.kind
172
186
  when :mapping
173
187
  node.each_pair do |k, v|
174
- check(k, aliases_enabled)
175
- check(v, aliases_enabled)
188
+ check(k, permitted, aliases_enabled)
189
+ check(v, permitted, aliases_enabled)
176
190
  end
177
191
  when :sequence
178
- node.each { |e| check(e, aliases_enabled) }
192
+ node.each { |e| check(e, permitted, aliases_enabled) }
179
193
  end
180
194
  end
181
195
  end
@@ -346,14 +360,9 @@ module Yeptris
346
360
  end
347
361
  end
348
362
 
349
- # The drop-in: rebind the top-level constant ( Psych-stdlib, if
350
- # already loaded, stays reachable as Yeptris::Psych::ORIGINAL).
351
- if defined?(::Psych) && !::Psych.equal?(Yeptris::Psych) &&
352
- !Yeptris::Psych.const_defined?(:ORIGINAL, false)
353
- Yeptris::Psych.const_set(:ORIGINAL, ::Psych)
354
- end
355
- # class_eval reaches Module-private methods WITHOUT send (the law:
356
- # no send to private methods); remove_const has no public form, and
357
- # the rebind is this namespace's whole purpose
358
- Object.class_eval { remove_const(:Psych) } if defined?(::Psych)
359
- ::Psych = Yeptris::Psych
363
+ # The drop-in is OPT-IN (issue #69): `require "yeptris/psych"` loads
364
+ # the namespace only and coexists with stdlib psych in ANY load
365
+ # order (this file never touches ::Psych). The rebind lives in
366
+ # yeptris/psych/drop_in — process-exclusive by nature, since the
367
+ # stdlib cannot be prevented from re-opening whatever ::Psych points
368
+ # at once IT loads.
data/lib/yeptris/yaml.rb CHANGED
@@ -22,6 +22,17 @@ module Yeptris
22
22
  docs.empty? ? nil : docs.first
23
23
  end
24
24
 
25
+ # Psych-semantics safe_load on the native surface (issue #69 —
26
+ # the entry frameworks actually want): plain data only; a leaf
27
+ # whose class is not permitted raises Yeptris::Psych::
28
+ # DisallowedClass; aliases: false raises Yeptris::Psych::
29
+ # AliasesError on alias use. Delegates to the compat namespace's
30
+ # tree walk (correctness first; the fused drain comes later).
31
+ def safe_load(yaml, permitted_classes: [], aliases: false, schema: :compat_11)
32
+ yaml = Yeptris.read_input(yaml)
33
+ Psych.safe_load(yaml.to_s, permitted_classes: permitted_classes, aliases: aliases)
34
+ end
35
+
25
36
  # Every document in the stream, in order.
26
37
  def load_stream(yaml, schema: :compat_11)
27
38
  yaml = Yeptris.read_input(yaml)
data/lib/yeptris.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Yeptris
4
4
  # The gem's version lives in the parent namespace's file — the last
5
5
  # internal require (yeptris/version) retired with it.
6
- VERSION = "0.1.32.1".freeze
6
+ VERSION = "0.2.0.1".freeze
7
7
  # The error hierarchy lives in THIS file (the parent namespace's
8
8
  # own file): nested constants do not trigger a parent-constant
9
9
  # autoload, and the law forbids internal requires — defining the
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yeptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.32.1
4
+ version: 0.2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -45,6 +45,7 @@ files:
45
45
  - lib/yeptris/node.rb
46
46
  - lib/yeptris/psych.rb
47
47
  - lib/yeptris/psych/coder_shim.rb
48
+ - lib/yeptris/psych/drop_in.rb
48
49
  - lib/yeptris/psych/encodable.rb
49
50
  - lib/yeptris/psych/handler.rb
50
51
  - lib/yeptris/psych/parser.rb