polyfill-data 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3fc564f62f95089c90ab7c84d558694513c676e2720e30a5587fda794b0446e2
4
+ data.tar.gz: 2466958db19b441691124b8085c60dbb16ad9522b257aa647bb5d816f6bb0b42
5
+ SHA512:
6
+ metadata.gz: '09a20ba5e0db01e1693fd27f63eafcd62e3cb6e7dbf49bc9f061e7bec5f9259f3cef29de156f5319791059ac152a169157dfbd4375b13e2f73f551511fb256b7'
7
+ data.tar.gz: 056fa220c31d080a4b3c3a68d606772bc8791495d42abcad66e80d59146568255d45a613411741223b82ddcc34ee5f3978099ed2aff79e4a9257d6720331dbff
checksums.yaml.gz.sig ADDED
Binary file
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Polyfill - Data
2
+
3
+ Add the Ruby 3.2 Data class to earlier Rubies.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add polyfill-data
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install polyfill-data
14
+
15
+ Polyfill-Data is cryptographically signed. To be sure the gem you install hasn’t been tampered with:
16
+
17
+ Add my the key (if you haven’t already) as a trusted certificate
18
+
19
+ gem cert --add <(curl -Ls https://raw.github.com/saturnflyer/polyfill-data/main/certs/saturnflyer.pem)
20
+
21
+ gem install polyfill-data -P HighSecurity
22
+
23
+ ## Usage
24
+
25
+ ```ruby
26
+ require 'polyfill-data'
27
+
28
+ MyValue = Data.define(:some, :stuff)
29
+ a_value = MyValue.new(some: "thing", stuff: "here")
30
+ puts a_value.to_h # => { some: "thing", stuff: "here" }
31
+
32
+ another = a_value.with(stuff: "there")
33
+ puts another.eql?(a_value) # => false
34
+ puts another.to_h # => { some: "thing", stuff: "there" }
35
+ ```
36
+
37
+ ## Development
38
+
39
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
40
+
41
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
42
+
43
+ ## Contributing
44
+
45
+ Bug reports and pull requests are welcome on GitHub at https://github.com/saturnflyer/polyfill-data.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/test_*.rb"]
10
+ end
11
+
12
+ task default: :test
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEPDCCAqSgAwIBAgIBATANBgkqhkiG9w0BAQsFADAkMSIwIAYDVQQDDBlqaW0v
3
+ REM9c2F0dXJuZmx5ZXIvREM9Y29tMB4XDTIzMDExOTE1MTcwNloXDTI0MDExOTE1
4
+ MTcwNlowJDEiMCAGA1UEAwwZamltL0RDPXNhdHVybmZseWVyL0RDPWNvbTCCAaIw
5
+ DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALujbiQtllLpXG8My8gDdiINTlT3
6
+ MVNwkagztozhLX/PWxekC1lBhCU9Eke2xRRcIZeK8CL/Hh984wN3H156J4b9yfUa
7
+ IoxKnItgCf2eDBJ0QMcaqgdfDdJp5km7+W0AdyOq5GuPGmGObPXReZWuB1FqS5z0
8
+ cRpoM/nOfYDI0T/obhBvcGt9mPibL4O5BnpJTj3X9NiMJ1KPv0zD0nlsEZy8iraY
9
+ P69pC/KykYIRM5hw4YYgFGjnftDFXoSdGRZ+wJn6Yb1MlJ4TMxRzSEZySZeSGlsk
10
+ tTVpGi3iftSJExvNWbilJqy73XtQHi846zCcqtVghwku3+0VbYr/0mygna4QzT/b
11
+ 2F4oW/1mu4aM/Phm+uyGcrmG2hioQqrZbOMGbi9Baa8xAob4HCUd1mfG+btjd61t
12
+ 5ckfDjqZLo0or9ATYU1F5G6kEJIjHiz5YgHxglcthQRHyWCa/r+M4DnpQ5TwBhhS
13
+ ZWoB5+W7KlfN1guDZ4LjDAUEsWCKsBNydM0XzQIDAQABo3kwdzAJBgNVHRMEAjAA
14
+ MAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUTNduUZSXfk8psUbclUtWl2qPf7MwHgYD
15
+ VR0RBBcwFYETamltQHNhdHVybmZseWVyLmNvbTAeBgNVHRIEFzAVgRNqaW1Ac2F0
16
+ dXJuZmx5ZXIuY29tMA0GCSqGSIb3DQEBCwUAA4IBgQBpRBA0939h4raDJmIObTGj
17
+ T4ZgUdOs27GnQXKJOG50Z9o8sEuG3WDRPUBsck50PKmI6taNalaEVOeeLNXvbfl8
18
+ Fb17rZnhy/ssAUseVAojIPHxHvsgi1K76v5HJMzuM774ftDckjWVOBhJ85Jxyj9c
19
+ 1VZes12ut2udsSa2vE6niS3mxrCeKCjmPQ7M5a55/fMr2tVX9qgPYZJmK0ck/Weh
20
+ e0fZ+W4iiGTZSrfHqNe2BabhLeKQtowVBMvBKbhL7DwdkufDaOv77uN5nsSMZfzh
21
+ ebdplnosS17xWRZxj+T/Vob93PmQFd7AsRnaNu9HjesRTbiBxKus7I0CeLPAelpD
22
+ Nq/5JAtQf+uEeL5/QXF9Mwv44ERxVbTX0DcZYjaepSgpYQtOew9EXLqQj0mLSsxG
23
+ dxkiKqcX+yzo9RJLD9l/E1AWX125r1Fhiif4l6ehdl7Vllc3NQUOm1abdmHtCYjw
24
+ dG3yPWBWzzN4ovoBRqsuTJbF1wjkCjl5ex5KhfYbeDc=
25
+ -----END CERTIFICATE-----
data/lib/data.rb ADDED
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "polyfill/data/version"
4
+
5
+ if RUBY_VERSION >= "3.2.0"
6
+ warn "You can remove the 'polyfill-data' gem now."
7
+ else
8
+ Object.send(:remove_const, :Data) rescue nil
9
+ class Data < Object
10
+ class << self
11
+ undef_method :new
12
+ end
13
+
14
+ def self.define(*args, &block)
15
+ raise ArgumentError if args.any?(/=/)
16
+ klass = ::Class.new(self, &block)
17
+
18
+ klass.define_singleton_method(:members) { args.map{ _1.intern } }
19
+
20
+ klass.define_singleton_method(:new) do |*new_args, **new_kwargs, &block|
21
+ arg_comparison = new_kwargs.any? ? new_kwargs.keys : new_args
22
+ if arg_comparison.size != args.size
23
+ raise ArgumentError
24
+ end
25
+ self.allocate.tap do |instance|
26
+ args_to_hash = if !new_kwargs.any?
27
+ Hash[members.take(new_args.size).zip(new_args)]
28
+ else
29
+ new_kwargs
30
+ end
31
+ instance.send(:initialize, **args_to_hash, &block)
32
+ end
33
+ end
34
+
35
+ args.map do |arg|
36
+ if klass.method_defined?(arg)
37
+ raise ArgumentError, "duplicate member #{arg}"
38
+ end
39
+ klass.define_method(arg) do
40
+ @attributes[arg]
41
+ end
42
+ end
43
+
44
+ klass
45
+ end
46
+
47
+ def members
48
+ self.class.members
49
+ end
50
+
51
+ def initialize(*args, **kwargs)
52
+ @attributes = case
53
+ when args.empty? && kwargs.empty?
54
+ {}
55
+ when args.empty?
56
+ kwargs
57
+ else
58
+ raise ArgumentError unless args.length == members.length
59
+ Hash[members.zip(args)]
60
+ end
61
+ end
62
+
63
+ def deconstruct_keys(array)
64
+ raise TypeError unless array.is_a?(Array) || array.nil?
65
+ return @attributes if array&.first.nil?
66
+
67
+ @attributes.slice(*array)
68
+ end
69
+
70
+ def to_h(&block)
71
+ @attributes.to_h(&block)
72
+ end
73
+
74
+ def hash
75
+ to_h.hash
76
+ end
77
+
78
+ def eql?(other)
79
+ self.class == other.class && hash == other.hash
80
+ end
81
+
82
+ def ==(other)
83
+ self.class == other.class && to_h == other.to_h
84
+ end
85
+
86
+ def inspect
87
+ name = ["data", self.class.name].compact.join(" ")
88
+ attribute_markers = @attributes.map do |key, value|
89
+ insect_key = key.to_s.start_with?("@") ? ":#{key}" : key
90
+ "#{insect_key}=#{value}"
91
+ end
92
+ %(#<#{name} #{attribute_markers.join(" ")}>)
93
+ end
94
+
95
+ def with(**kwargs)
96
+ self.class.new(*@attributes.merge(kwargs).values)
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polyfill
4
+ module Data
5
+ VERSION = "1.0.0"
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ require "data"
data/test/test_data.rb ADDED
@@ -0,0 +1,170 @@
1
+ # -*- coding: us-ascii -*-
2
+ # frozen_string_literal: false
3
+ require 'test_helper'
4
+
5
+ class TestData < Minitest::Test
6
+ def test_define
7
+ klass = Data.define(:foo, :bar)
8
+ assert_kind_of(Class, klass)
9
+ assert_equal(%i[foo bar], klass.members)
10
+
11
+ assert_raises(NoMethodError) { Data.new(:foo) }
12
+ assert_raises(TypeError) { Data.define(0) }
13
+
14
+ # Because some code is shared with Struct, check we don't share unnecessary functionality
15
+ assert_raises(TypeError) { Data.define(:foo, keyword_init: true) }
16
+ end
17
+
18
+ def test_define_edge_cases
19
+ # non-ascii
20
+ klass = Data.define(:"r\u{e9}sum\u{e9}")
21
+ o = klass.new(1)
22
+ assert_equal(1, o.send(:"r\u{e9}sum\u{e9}"))
23
+
24
+ # junk string
25
+ klass = Data.define(:"a\000")
26
+ o = klass.new(1)
27
+ assert_equal(1, o.send(:"a\000"))
28
+
29
+ # special characters in attribute names
30
+ klass = Data.define(:a, :b?)
31
+ x = Object.new
32
+ o = klass.new("test", x)
33
+ assert_same(x, o.b?)
34
+
35
+ klass = Data.define(:a, :b!)
36
+ x = Object.new
37
+ o = klass.new("test", x)
38
+ assert_same(x, o.b!)
39
+
40
+ assert_raises(ArgumentError) { Data.define(:x=) }
41
+ assert_raises(ArgumentError, /duplicate member/) { Data.define(:x, :x) }
42
+ end
43
+
44
+ def test_define_with_block
45
+ klass = Data.define(:a, :b) do
46
+ def c
47
+ a + b
48
+ end
49
+ end
50
+
51
+ assert_equal(3, klass.new(1, 2).c)
52
+ end
53
+
54
+ def test_initialize
55
+ klass = Data.define(:foo, :bar)
56
+
57
+ # Regular
58
+ test = klass.new(1, 2)
59
+ assert_equal(1, test.foo)
60
+ assert_equal(2, test.bar)
61
+ assert_equal(test, klass.new(1, 2))
62
+
63
+ # Keywords
64
+ test_kw = klass.new(foo: 1, bar: 2)
65
+ assert_equal(1, test_kw.foo)
66
+ assert_equal(2, test_kw.bar)
67
+ assert_equal(test_kw, klass.new(foo: 1, bar: 2))
68
+ assert_equal(test_kw, test)
69
+
70
+ # Wrong protocol
71
+ assert_raises(ArgumentError) { klass.new(1) }
72
+ assert_raises(ArgumentError) { klass.new(1, 2, 3) }
73
+ assert_raises(ArgumentError) { klass.new(foo: 1) }
74
+ assert_raises(ArgumentError) { klass.new(foo: 1, bar: 2, baz: 3) }
75
+ # Could be converted to foo: 1, bar: 2, but too smart is confusing
76
+ assert_raises(ArgumentError) { klass.new(1, bar: 2) }
77
+ end
78
+
79
+ def test_initialize_redefine
80
+ klass = Data.define(:foo, :bar) do
81
+ attr_reader :passed
82
+
83
+ def initialize(*args, **kwargs)
84
+ @passed = [args, kwargs]
85
+
86
+ super(foo: 1, bar: 2) # so we can experiment with passing wrong numbers of args
87
+ end
88
+ end
89
+ # require 'debug'; debugger
90
+ assert_equal([[], {foo: 1, bar: 2}], klass.new(foo: 1, bar: 2).passed)
91
+
92
+ # Positional arguments are converted to keyword ones
93
+ assert_equal([[], {foo: 1, bar: 2}], klass.new(1, 2).passed)
94
+
95
+ # Missing arguments can be fixed in initialize
96
+ assert_equal([[], {foo: 1}], klass.new(foo: 1).passed)
97
+
98
+ # Extra keyword arguments can be dropped in initialize
99
+ assert_equal([[], {foo: 1, bar: 2, baz: 3}], klass.new(foo: 1, bar: 2, baz: 3).passed)
100
+ end
101
+
102
+ def test_instance_behavior
103
+ klass = Data.define(:foo, :bar)
104
+
105
+ test = klass.new(1, 2)
106
+ assert_equal(1, test.foo)
107
+ assert_equal(2, test.bar)
108
+ assert_equal(%i[foo bar], test.members)
109
+ assert_equal(1, test.public_send(:foo))
110
+ assert_equal(0, test.method(:foo).arity)
111
+ assert_equal([], test.method(:foo).parameters)
112
+
113
+ assert_equal({foo: 1, bar: 2}, test.to_h)
114
+ assert_equal({"foo"=>"1", "bar"=>"2"}, test.to_h { [_1.to_s, _2.to_s] })
115
+
116
+ assert_equal({foo: 1, bar: 2}, test.deconstruct_keys(nil))
117
+ assert_equal({foo: 1}, test.deconstruct_keys(%i[foo]))
118
+ assert_equal({foo: 1}, test.deconstruct_keys(%i[foo baz]))
119
+ assert_raises(TypeError) { test.deconstruct_keys(0) }
120
+
121
+ assert_kind_of(Integer, test.hash)
122
+ end
123
+
124
+ def test_inspect
125
+ klass = Data.define(:a)
126
+ o = klass.new(1)
127
+ assert_equal("#<data a=1>", o.inspect)
128
+
129
+ Object.const_set(:Foo, klass)
130
+ assert_equal("#<data Foo a=1>", o.inspect)
131
+ Object.instance_eval { remove_const(:Foo) }
132
+
133
+ klass = Data.define(:@a)
134
+ o = klass.new(1)
135
+ assert_equal("#<data :@a=1>", o.inspect)
136
+ end
137
+
138
+ def test_equal
139
+ klass1 = Data.define(:a)
140
+ klass2 = Data.define(:a)
141
+ o1 = klass1.new(1)
142
+ o2 = klass1.new(1)
143
+ o3 = klass2.new(1)
144
+ assert_equal(o1, o2)
145
+ refute_equal(o1, o3)
146
+ end
147
+
148
+ def test_eql
149
+ klass1 = Data.define(:a)
150
+ klass2 = Data.define(:a)
151
+ o1 = klass1.new(1)
152
+ o2 = klass1.new(1)
153
+ o3 = klass2.new(1)
154
+ assert_operator(o1, :eql?, o2)
155
+ refute_operator(o1, :eql?, o3)
156
+ end
157
+
158
+ def test_memberless
159
+ klass = Data.define
160
+
161
+ test = klass.new
162
+
163
+ assert_equal(klass.new, test)
164
+ refute_equal(Data.define.new, test)
165
+
166
+ assert_equal('#<data >', test.inspect)
167
+ assert_equal([], test.members)
168
+ assert_equal({}, test.to_h)
169
+ end
170
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ require "data"
5
+ require "minitest/autorun"
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: polyfill-data
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jim Gay
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEPDCCAqSgAwIBAgIBATANBgkqhkiG9w0BAQsFADAkMSIwIAYDVQQDDBlqaW0v
14
+ REM9c2F0dXJuZmx5ZXIvREM9Y29tMB4XDTIzMDExOTE1MTcwNloXDTI0MDExOTE1
15
+ MTcwNlowJDEiMCAGA1UEAwwZamltL0RDPXNhdHVybmZseWVyL0RDPWNvbTCCAaIw
16
+ DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALujbiQtllLpXG8My8gDdiINTlT3
17
+ MVNwkagztozhLX/PWxekC1lBhCU9Eke2xRRcIZeK8CL/Hh984wN3H156J4b9yfUa
18
+ IoxKnItgCf2eDBJ0QMcaqgdfDdJp5km7+W0AdyOq5GuPGmGObPXReZWuB1FqS5z0
19
+ cRpoM/nOfYDI0T/obhBvcGt9mPibL4O5BnpJTj3X9NiMJ1KPv0zD0nlsEZy8iraY
20
+ P69pC/KykYIRM5hw4YYgFGjnftDFXoSdGRZ+wJn6Yb1MlJ4TMxRzSEZySZeSGlsk
21
+ tTVpGi3iftSJExvNWbilJqy73XtQHi846zCcqtVghwku3+0VbYr/0mygna4QzT/b
22
+ 2F4oW/1mu4aM/Phm+uyGcrmG2hioQqrZbOMGbi9Baa8xAob4HCUd1mfG+btjd61t
23
+ 5ckfDjqZLo0or9ATYU1F5G6kEJIjHiz5YgHxglcthQRHyWCa/r+M4DnpQ5TwBhhS
24
+ ZWoB5+W7KlfN1guDZ4LjDAUEsWCKsBNydM0XzQIDAQABo3kwdzAJBgNVHRMEAjAA
25
+ MAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUTNduUZSXfk8psUbclUtWl2qPf7MwHgYD
26
+ VR0RBBcwFYETamltQHNhdHVybmZseWVyLmNvbTAeBgNVHRIEFzAVgRNqaW1Ac2F0
27
+ dXJuZmx5ZXIuY29tMA0GCSqGSIb3DQEBCwUAA4IBgQBpRBA0939h4raDJmIObTGj
28
+ T4ZgUdOs27GnQXKJOG50Z9o8sEuG3WDRPUBsck50PKmI6taNalaEVOeeLNXvbfl8
29
+ Fb17rZnhy/ssAUseVAojIPHxHvsgi1K76v5HJMzuM774ftDckjWVOBhJ85Jxyj9c
30
+ 1VZes12ut2udsSa2vE6niS3mxrCeKCjmPQ7M5a55/fMr2tVX9qgPYZJmK0ck/Weh
31
+ e0fZ+W4iiGTZSrfHqNe2BabhLeKQtowVBMvBKbhL7DwdkufDaOv77uN5nsSMZfzh
32
+ ebdplnosS17xWRZxj+T/Vob93PmQFd7AsRnaNu9HjesRTbiBxKus7I0CeLPAelpD
33
+ Nq/5JAtQf+uEeL5/QXF9Mwv44ERxVbTX0DcZYjaepSgpYQtOew9EXLqQj0mLSsxG
34
+ dxkiKqcX+yzo9RJLD9l/E1AWX125r1Fhiif4l6ehdl7Vllc3NQUOm1abdmHtCYjw
35
+ dG3yPWBWzzN4ovoBRqsuTJbF1wjkCjl5ex5KhfYbeDc=
36
+ -----END CERTIFICATE-----
37
+ date: 2023-01-19 00:00:00.000000000 Z
38
+ dependencies: []
39
+ description: Add the ruby 3.2 Data class to older rubies
40
+ email:
41
+ - jim@saturnflyer.com
42
+ executables: []
43
+ extensions: []
44
+ extra_rdoc_files: []
45
+ files:
46
+ - README.md
47
+ - Rakefile
48
+ - certs/saturnflyer.pem
49
+ - lib/data.rb
50
+ - lib/polyfill-data.rb
51
+ - lib/polyfill/data/version.rb
52
+ - test/test_data.rb
53
+ - test/test_helper.rb
54
+ homepage: https://github.com/saturnflyer/polyfill-data
55
+ licenses:
56
+ - MIT
57
+ metadata:
58
+ homepage_uri: https://github.com/saturnflyer/polyfill-data
59
+ source_code_uri: https://github.com/saturnflyer/polyfill-data.git
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 2.6.0
69
+ - - "<"
70
+ - !ruby/object:Gem::Version
71
+ version: 3.2.0
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubygems_version: 3.2.27
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Add the ruby 3.2 Data class to older rubies
82
+ test_files:
83
+ - test/test_data.rb
84
+ - test/test_helper.rb
metadata.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+
2
+ }d94@T'��ε\�,���Ӧ �;e����8F�x�K��*�����,� �++'qաt�ԝ�k �*,�㑩�Ci{&��H���8���ֱ7!#��R����ڎ˟M�A������.�p��뽏��c֭5�����D{C��[�l��D\��e��1>&�Z���^�:� !n�5�끼�V��8"�o�e��8mK�G*��F�l��� N�s��88:��c�'+"�ۊ�����Pt�,����<&��aV��A舀
3
+ [:�I{y%[���Vi@���v���8�e���������sw���^���