dry-struct 1.0.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "weakref"
4
+ require "dry/types/compiler"
5
+
6
+ module Dry
7
+ class Struct
8
+ class Compiler < Types::Compiler
9
+ def visit_struct(node)
10
+ struct, _ = node
11
+
12
+ struct.__getobj__
13
+ rescue ::WeakRef::RefError
14
+ if struct.weakref_alive?
15
+ raise
16
+ else
17
+ raise RecycledStructError
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,29 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  class Struct
3
- class Constructor
4
- include Dry::Equalizer(:type)
5
- include Dry::Types::Type
6
-
7
- # @return [#call]
8
- attr_reader :fn
9
-
10
- # @return [#call]
11
- attr_reader :type
12
-
13
- # @param [Struct] type
14
- # @param [Hash] options
15
- # @param [#call, nil] block
16
- def initialize(type, options = {}, &block)
17
- @type = type
18
- @fn = options.fetch(:fn, block)
19
- end
20
-
21
- # @param [Object] input
22
- # @return [Object]
23
- def call(input)
24
- type[fn[input]]
25
- end
26
- alias_method :[], :call
5
+ class Constructor < Types::Constructor
6
+ alias_method :primitive, :type
27
7
  end
28
8
  end
29
9
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  class Struct
3
5
  # Raised when given input doesn't conform schema and constructor type
4
6
  Error = Class.new(TypeError)
5
7
 
6
8
  # Raised when defining duplicate attributes
7
- class RepeatedAttributeError < ArgumentError
9
+ class RepeatedAttributeError < ::ArgumentError
8
10
  # @param [Symbol] key
9
11
  # attribute name that is the same as previously defined one
10
12
  def initialize(key)
@@ -13,9 +15,17 @@ module Dry
13
15
  end
14
16
 
15
17
  # Raised when a struct doesn't have an attribute
16
- class MissingAttributeError < KeyError
18
+ class MissingAttributeError < ::KeyError
17
19
  def initialize(key)
18
- super("Missing attribute: #{ key.inspect }")
20
+ super("Missing attribute: #{key.inspect}")
21
+ end
22
+ end
23
+
24
+ # When struct class stored in ast was garbage collected because no alive objects exists
25
+ # This shouldn't happen in a working application
26
+ class RecycledStructError < ::RuntimeError
27
+ def initialize
28
+ super("Reference to struct class was garbage collected")
19
29
  end
20
30
  end
21
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dry::Struct.register_extension(:pretty_print) do
2
- require 'dry/struct/extensions/pretty_print'
4
+ require "dry/struct/extensions/pretty_print"
3
5
  end
@@ -1,16 +1,18 @@
1
- require 'pp'
1
+ # frozen_string_literal: true
2
+
3
+ require "pp"
2
4
 
3
5
  module Dry
4
6
  class Struct
5
7
  def pretty_print(pp)
6
8
  klass = self.class
7
- pp.group(1, "#<#{ klass.name || klass.inspect }", '>') do
8
- pp.seplist(@attributes.keys, proc { pp.text ',' }) do |column_name|
9
+ pp.group(1, "#<#{klass.name || klass.inspect}", ">") do
10
+ pp.seplist(@attributes.keys, proc { pp.text "," }) do |column_name|
9
11
  column_value = @attributes[column_name]
10
- pp.breakable ' '
12
+ pp.breakable " "
11
13
  pp.group(1) do
12
14
  pp.text column_name
13
- pp.text '='
15
+ pp.text "="
14
16
  pp.pp column_value
15
17
  end
16
18
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  class Struct
3
5
  # Helper for {Struct#to_hash} implementation
@@ -6,12 +8,10 @@ module Dry
6
8
  # @param [#to_hash, #map, Object] value
7
9
  # @return [Hash, Array]
8
10
  def self.[](value)
9
- if value.respond_to?(:to_hash)
10
- if RUBY_VERSION >= '2.4'
11
- value.to_hash.transform_values { |v| self[v] }
12
- else
13
- value.to_hash.each_with_object({}) { |(k, v), h| h[k] = self[v] }
14
- end
11
+ if value.is_a?(Struct)
12
+ value.to_h.transform_values { |current| self[current] }
13
+ elsif value.respond_to?(:to_hash)
14
+ value.to_hash.transform_values { |current| self[current] }
15
15
  elsif value.respond_to?(:to_ary)
16
16
  value.to_ary.map { |item| self[item] }
17
17
  else
@@ -1,10 +1,13 @@
1
- require 'dry/types/printer'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/types/printer"
2
4
 
3
5
  module Dry
4
6
  module Types
5
7
  # @api private
6
8
  class Printer
7
9
  MAPPING[Struct::Sum] = :visit_struct_sum
10
+ MAPPING[Struct::Constructor] = :visit_struct_constructor
8
11
 
9
12
  def visit_struct_sum(sum)
10
13
  visit_sum_constructors(sum) do |constructors|
@@ -13,6 +16,8 @@ module Dry
13
16
  end
14
17
  end
15
18
  end
19
+
20
+ alias_method :visit_struct_constructor, :visit_constructor
16
21
  end
17
22
  end
18
23
  end
@@ -1,28 +1,42 @@
1
- require 'dry/types/compiler'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/struct/compiler"
2
4
 
3
5
  module Dry
4
6
  class Struct
5
7
  # @private
6
- class StructBuilder < Dry::Types::Compiler
8
+ class StructBuilder < Compiler
7
9
  attr_reader :struct
8
10
 
9
11
  def initialize(struct)
10
- super(Dry::Types)
12
+ super(Types)
11
13
  @struct = struct
12
14
  end
13
15
 
14
16
  # @param [Symbol|String] attr_name the name of the nested type
15
- # @param [Dry::Struct,Dry::Types::Type::Array] type the superclass of the nested struct
17
+ # @param [Dry::Struct,Dry::Types::Type::Array,Undefined] type the superclass of the nested struct
16
18
  # @yield the body of the nested struct
17
19
  def call(attr_name, type, &block)
18
20
  const_name = const_name(type, attr_name)
19
21
  check_name(const_name)
20
22
 
21
- new_type = Class.new(parent(type), &block)
23
+ builder = self
24
+ parent = parent(type)
25
+
26
+ new_type = ::Class.new(Undefined.default(parent, struct.abstract_class)) do
27
+ if Undefined.equal?(parent)
28
+ schema builder.struct.schema.clear
29
+ end
30
+
31
+ class_exec(&block)
32
+ end
33
+
22
34
  struct.const_set(const_name, new_type)
23
35
 
24
36
  if array?(type)
25
37
  type.of(new_type)
38
+ elsif optional?(type)
39
+ new_type.optional
26
40
  else
27
41
  new_type
28
42
  end
@@ -30,37 +44,46 @@ module Dry
30
44
 
31
45
  private
32
46
 
47
+ def type?(type)
48
+ type.is_a?(Types::Type)
49
+ end
50
+
33
51
  def array?(type)
34
- type.is_a?(Types::Type) && type.primitive.equal?(Array)
52
+ type?(type) && !type.optional? && type.primitive.equal?(::Array)
53
+ end
54
+
55
+ def optional?(type)
56
+ type?(type) && type.optional?
35
57
  end
36
58
 
37
59
  def parent(type)
38
60
  if array?(type)
39
61
  visit(type.to_ast)
62
+ elsif optional?(type)
63
+ type.right
40
64
  else
41
- type || default_superclass
65
+ type
42
66
  end
43
67
  end
44
68
 
45
- def default_superclass
46
- struct < Value ? Value : Struct
47
- end
48
-
49
69
  def const_name(type, attr_name)
50
- snake_name = if array?(type)
51
- Dry::Core::Inflector.singularize(attr_name)
52
- else
53
- attr_name
54
- end
55
-
56
- Dry::Core::Inflector.camelize(snake_name)
70
+ snake_name =
71
+ if array?(type)
72
+ Core::Inflector.singularize(attr_name)
73
+ else
74
+ attr_name
75
+ end
76
+
77
+ Core::Inflector.camelize(snake_name)
57
78
  end
58
79
 
59
80
  def check_name(name)
60
- raise(
61
- Struct::Error,
62
- "Can't create nested attribute - `#{struct}::#{name}` already defined"
63
- ) if struct.const_defined?(name, false)
81
+ if struct.const_defined?(name, false)
82
+ raise(
83
+ Error,
84
+ "Can't create nested attribute - `#{struct}::#{name}` already defined"
85
+ )
86
+ end
64
87
  end
65
88
 
66
89
  def visit_constrained(node)
@@ -70,11 +93,11 @@ module Dry
70
93
 
71
94
  def visit_array(node)
72
95
  member, * = node
73
- member
96
+ visit(member)
74
97
  end
75
98
 
76
99
  def visit_nominal(*)
77
- default_superclass
100
+ Undefined
78
101
  end
79
102
 
80
103
  def visit_constructor(node)
@@ -1,5 +1,7 @@
1
- require 'dry/types/sum'
2
- require 'dry/types/printer'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/types/sum"
4
+ require "dry/types/printer"
3
5
 
4
6
  module Dry
5
7
  class Struct
@@ -12,6 +14,7 @@ module Dry
12
14
  right.try_struct(input) { super }
13
15
  end
14
16
  end
17
+
15
18
  # @param [Hash{Symbol => Object},Dry::Struct] input
16
19
  # @yieldparam [Dry::Types::Result::Failure] failure
17
20
  # @yieldreturn [Dry::Types::ResultResult]
@@ -1,14 +1,19 @@
1
- require 'ice_nine'
1
+ # frozen_string_literal: true
2
+
3
+ require "ice_nine"
4
+ require "dry/core/deprecations"
2
5
 
3
6
  module Dry
4
7
  class Struct
8
+ extend Core::Deprecations[:'dry-struct']
9
+
5
10
  # {Value} objects behave like {Struct}s but *deeply frozen*
6
11
  # using [`ice_nine`](https://github.com/dkubb/ice_nine)
7
12
  #
8
13
  # @example
9
14
  # class Location < Dry::Struct::Value
10
- # attribute :lat, Types::Strict::Float
11
- # attribute :lng, Types::Strict::Float
15
+ # attribute :lat, Types::Float
16
+ # attribute :lng, Types::Float
12
17
  # end
13
18
  #
14
19
  # loc1 = Location.new(lat: 1.23, lng: 4.56)
@@ -20,12 +25,16 @@ module Dry
20
25
  #
21
26
  # @see https://github.com/dkubb/ice_nine
22
27
  class Value < self
28
+ abstract
29
+
23
30
  # @param (see ClassInterface#new)
24
31
  # @return [Value]
25
32
  # @see https://github.com/dkubb/ice_nine
26
33
  def self.new(*)
27
- IceNine.deep_freeze(super)
34
+ ::IceNine.deep_freeze(super)
28
35
  end
29
36
  end
37
+
38
+ deprecate_constant :Value
30
39
  end
31
40
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  class Struct
3
5
  # @private
4
- VERSION = '1.0.0'.freeze
6
+ VERSION = "1.4.0"
5
7
  end
6
8
  end
metadata CHANGED
@@ -1,63 +1,49 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-23 00:00:00.000000000 Z
11
+ date: 2021-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: dry-equalizer
14
+ name: dry-core
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.2'
19
+ version: '0.5'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: '0.5'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '0.2'
29
+ version: '0.5'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0.5'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: dry-types
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '1.0'
39
+ version: '1.5'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '1.0'
41
- - !ruby/object:Gem::Dependency
42
- name: dry-core
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.4'
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: 0.4.3
51
- type: :runtime
52
- prerelease: false
53
- version_requirements: !ruby/object:Gem::Requirement
54
- requirements:
55
- - - "~>"
56
- - !ruby/object:Gem::Version
57
- version: '0.4'
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 0.4.3
46
+ version: '1.5'
61
47
  - !ruby/object:Gem::Dependency
62
48
  name: ice_nine
63
49
  requirement: !ruby/object:Gem::Requirement
@@ -90,71 +76,59 @@ dependencies:
90
76
  name: rake
91
77
  requirement: !ruby/object:Gem::Requirement
92
78
  requirements:
93
- - - "~>"
79
+ - - ">="
94
80
  - !ruby/object:Gem::Version
95
- version: '11.0'
81
+ version: '0'
96
82
  type: :development
97
83
  prerelease: false
98
84
  version_requirements: !ruby/object:Gem::Requirement
99
85
  requirements:
100
- - - "~>"
86
+ - - ">="
101
87
  - !ruby/object:Gem::Version
102
- version: '11.0'
88
+ version: '0'
103
89
  - !ruby/object:Gem::Dependency
104
90
  name: rspec
105
91
  requirement: !ruby/object:Gem::Requirement
106
92
  requirements:
107
- - - "~>"
93
+ - - ">="
108
94
  - !ruby/object:Gem::Version
109
- version: '3.3'
95
+ version: '0'
110
96
  type: :development
111
97
  prerelease: false
112
98
  version_requirements: !ruby/object:Gem::Requirement
113
99
  requirements:
114
- - - "~>"
100
+ - - ">="
115
101
  - !ruby/object:Gem::Version
116
- version: '3.3'
102
+ version: '0'
117
103
  - !ruby/object:Gem::Dependency
118
104
  name: yard
119
105
  requirement: !ruby/object:Gem::Requirement
120
106
  requirements:
121
- - - "~>"
107
+ - - ">="
122
108
  - !ruby/object:Gem::Version
123
- version: 0.9.5
109
+ version: '0'
124
110
  type: :development
125
111
  prerelease: false
126
112
  version_requirements: !ruby/object:Gem::Requirement
127
113
  requirements:
128
- - - "~>"
114
+ - - ">="
129
115
  - !ruby/object:Gem::Version
130
- version: 0.9.5
131
- description: Typed structs and value objects.
116
+ version: '0'
117
+ description: Typed structs and value objects
132
118
  email:
133
119
  - piotr.solnica@gmail.com
134
120
  executables: []
135
121
  extensions: []
136
122
  extra_rdoc_files: []
137
123
  files:
138
- - ".gitignore"
139
- - ".rspec"
140
- - ".travis.yml"
141
- - ".yardopts"
142
124
  - CHANGELOG.md
143
- - CONTRIBUTING.md
144
- - Gemfile
145
125
  - LICENSE
146
126
  - README.md
147
- - Rakefile
148
- - benchmarks/basic.rb
149
- - benchmarks/constrained.rb
150
- - benchmarks/profile_instantiation.rb
151
- - benchmarks/setup.rb
152
- - bin/console
153
- - bin/setup
154
127
  - dry-struct.gemspec
155
128
  - lib/dry-struct.rb
156
129
  - lib/dry/struct.rb
157
130
  - lib/dry/struct/class_interface.rb
131
+ - lib/dry/struct/compiler.rb
158
132
  - lib/dry/struct/constructor.rb
159
133
  - lib/dry/struct/errors.rb
160
134
  - lib/dry/struct/extensions.rb
@@ -165,14 +139,14 @@ files:
165
139
  - lib/dry/struct/sum.rb
166
140
  - lib/dry/struct/value.rb
167
141
  - lib/dry/struct/version.rb
168
- - log/.gitkeep
169
- homepage: https://github.com/dry-rb/dry-struct
142
+ homepage: https://dry-rb.org/gems/dry-struct
170
143
  licenses:
171
144
  - MIT
172
145
  metadata:
173
146
  allowed_push_host: https://rubygems.org
174
147
  changelog_uri: https://github.com/dry-rb/dry-struct/blob/master/CHANGELOG.md
175
148
  source_code_uri: https://github.com/dry-rb/dry-struct
149
+ bug_tracker_uri: https://github.com/dry-rb/dry-struct/issues
176
150
  post_install_message:
177
151
  rdoc_options: []
178
152
  require_paths:
@@ -181,15 +155,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
181
155
  requirements:
182
156
  - - ">="
183
157
  - !ruby/object:Gem::Version
184
- version: 2.4.0
158
+ version: 2.5.0
185
159
  required_rubygems_version: !ruby/object:Gem::Requirement
186
160
  requirements:
187
161
  - - ">="
188
162
  - !ruby/object:Gem::Version
189
163
  version: '0'
190
164
  requirements: []
191
- rubygems_version: 3.0.3
165
+ rubygems_version: 3.1.4
192
166
  signing_key:
193
167
  specification_version: 4
194
- summary: Typed structs and value objects.
168
+ summary: Typed structs and value objects
195
169
  test_files: []