l43_base 0.1.0 → 0.1.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: 80a1f55728d1bde85d95be0c9a6578ebc5c48741224cdbef3f3ea3cee4208140
4
- data.tar.gz: 900b22d8c1623ace5f39e0d4e31f9913140dcdda3f26f62abd30eb095ccffe5d
3
+ metadata.gz: 9675c29f54a7aea812466a54b533acbb1c224e9f4904514f3e81c5bf7cdfca5a
4
+ data.tar.gz: 5f27143f5677c6e95b548875c36c4a2197568b09e9df0d5d6fd8feda1e2cef77
5
5
  SHA512:
6
- metadata.gz: '035865b356f7c7ab01611faafffae4bebca2581a9b5769540fd2db4e518d2542af07798cee6ace287a7f2e2ba36d892ecc4f4c9a1e3e2e09515820165a2d73e1'
7
- data.tar.gz: 610e0f965e14ac7ca81e9ee53f6e560a8fd836c9b15fd6ed6a4205c3e9f54d3ac0eb7856f1366e304c0e6d17d4d93545bd64fecd3352899dc8d13bb113c7260d
6
+ metadata.gz: aad4d74bdb3344c40128a9e110c4d08c8ebc411c8739d1ccab4b016fd30922eb4748b9fe709d4d89dd8486d4d005ad471d7a96df8699c6c50d340c175d4c6fea
7
+ data.tar.gz: 7ca068e33271f04610a6fb9492938f737389b1aae080e2f2bd5fe4e70e41039ae57bdbf3565049533104403f563b5e053fabceeed4b36f477d9a05fa4021d10d
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module L43
4
+ module Base
5
+ module DataClass
6
+ class Attribute
7
+ attr_reader :default, :init, :name, :required
8
+
9
+ private
10
+ def initialize(name:, required:, default:, &init)
11
+ @name = name
12
+ @required = required
13
+ @default = default
14
+ @init = init
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
21
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -1,23 +1,57 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative './data_class_class'
4
+ require_relative './attribute'
4
5
  module L43
5
6
  module Base
6
7
  module DataClass
7
8
  class DataClassMaker
8
9
 
9
- attr_reader :block_name, :klass
10
+ attr_reader :block_name, :block_required, :defaulted, :klass
11
+
12
+ def defattr(name, required: false, default: Undefined, &init)
13
+ raise ArgumentError, "must not redefine attribute #{name}" if attributes[name]
14
+ attributes.update(name => Attribute.new(name:, required:, default:, &init))
15
+ self
16
+ end
10
17
 
11
18
  def define(*required, **defaulted, &blk)
19
+ add_required_attributes(required)
20
+ add_defaulted_attributes(defaulted)
12
21
  @klass = Class.new(DataClassClass)
13
- define_klass(required:, defaulted:)
22
+ define_klass
14
23
  klass.module_eval(&blk) if blk
15
24
  klass.freeze
16
25
  end
17
26
 
27
+ def attributes = @__attributes__ ||= {}
28
+
29
+ def defaults
30
+ @__defaults__ ||= attributes
31
+ .values
32
+ .reject { it.default == Undefined }
33
+ .map { [it.name, it.default] }
34
+ .to_h
35
+ end
36
+
37
+ def required_att_names = @__required_att_names__ ||= attributes.values.select(&:required).map(&:name)
38
+
18
39
  private
19
- def initialize(block_name: nil)
40
+ def initialize(block_name: nil, block_required: false)
20
41
  @block_name = block_name
42
+ @block_required = block_required
43
+ end
44
+
45
+ def add_defaulted_attributes(defaulted)
46
+ defaulted.each do |name, default|
47
+ defattr(name, default:)
48
+ end
49
+ end
50
+
51
+ def add_required_attributes(required)
52
+ required.each do
53
+ defattr(it, required: true)
54
+ end
21
55
  end
22
56
 
23
57
  def define_accessors(names:)
@@ -26,12 +60,9 @@ module L43
26
60
  }
27
61
  end
28
62
 
29
- def define_klass(required:, defaulted:)
30
- delta = required.intersection(defaulted.keys)
31
- raise ArgumentError, "incoherant attribute definition, arg must not be required and defaulted, violating args: #{delta.inspect}" unless delta.empty?
32
-
33
- init_instance(block_name:, required:, defaulted:)
34
- names = required + defaulted.keys
63
+ def define_klass
64
+ init_instance
65
+ names = attributes.keys
35
66
  names = names << block_name if block_name
36
67
  define_update(names:)
37
68
  define_accessors(names:)
@@ -63,24 +94,28 @@ module L43
63
94
  end
64
95
  end
65
96
 
66
- def init_instance(block_name:, required:, defaulted:)
97
+ def init_instance
98
+ data = self
67
99
  klass.define_method :initialize do |**kwds, &blk|
68
- if block_name
100
+ raise ArgumentError, "block argument required" if data.block_required && !blk
101
+ if data.block_name
69
102
  if blk
70
103
  b = -> { instance_exec(&blk) }
71
- instance_variable_set("@#{block_name}", b)
104
+ instance_variable_set("@#{data.block_name}", b)
72
105
  end
73
106
  else
74
107
  raise ArgumentError, "block argument not supported" if blk
75
108
  end
76
109
 
77
- missing = required - kwds.keys
110
+ missing = data.required_att_names - kwds.keys
78
111
  raise ArgumentError, "missing required keyword parameters: #{missing.inspect}" unless missing.empty?
79
- spurious = kwds.keys - required - defaulted.keys
112
+ spurious = kwds.keys - data.attributes.keys
80
113
  raise ArgumentError, "spurious keyword parameters: #{spurious.inspect}" unless spurious.empty?
81
114
 
82
- values = defaulted.merge(kwds)
115
+ values = data.defaults.merge(kwds)
83
116
  values.each do |key, value|
117
+ init = data.attributes.fetch(key).init
118
+ value = init ? init.(value) : value
84
119
  instance_variable_set("@#{key}", value)
85
120
  end
86
121
 
@@ -5,6 +5,10 @@ module L43
5
5
  module Base
6
6
  module DataClass extend self
7
7
 
8
+ def defattr(name, required: false, default: Undefined, &init)
9
+ DataClassMaker.new.defattr(name, required:, default:, &init)
10
+ end
11
+
8
12
  def define(*a, **k, &b)
9
13
  DataClassMaker.new.define(*a, **k, &b)
10
14
  end
@@ -13,6 +17,10 @@ module L43
13
17
  DataClassMaker.new(block_name:)
14
18
  end
15
19
 
20
+ def with_block!(block_name)
21
+ DataClassMaker.new(block_name:, block_required: true)
22
+ end
23
+
16
24
  end
17
25
  end
18
26
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module L43
4
4
  module Base
5
- VERSION = '0.1.0'
5
+ VERSION = '0.1.1'
6
6
  end
7
7
  end
8
8
  # SPDX-License-Identifier: AGPL-3.0-or-later
data/lib/l43/base.rb CHANGED
@@ -4,6 +4,8 @@ require_relative 'r'
4
4
  module L43
5
5
  require_all __FILE__
6
6
  module Base
7
+ Undefined = Object.new.freeze
8
+
7
9
  def DataClass(*a, **k, &b) = DataClass.define(*a, **k, &b)
8
10
  end
9
11
  end
data/lib/l43/r.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module L43
4
- def self.require_all(file, descend: false)
5
- dir = file.sub(/\.[^.]*\z/, '')
6
- wc = descend ? '/**/*.rb' : '/*.rb'
7
- Dir.glob(File.join(dir, wc)).each { require it }
8
- end
4
+ def self.require_all(file, descend: false)
5
+ dir = file.sub(/\.[^.]*\z/, '')
6
+ wc = descend ? '/**/*.rb' : '/*.rb'
7
+ Dir.glob(File.join(dir, wc)).each { require it }
8
+ end
9
9
  end
10
10
  # SPDX-License-Identifier: AGPL-3.0-or-later
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: l43_base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Dober
@@ -33,6 +33,7 @@ extra_rdoc_files: []
33
33
  files:
34
34
  - lib/l43/base.rb
35
35
  - lib/l43/base/data_class.rb
36
+ - lib/l43/base/data_class/attribute.rb
36
37
  - lib/l43/base/data_class/data_class_class.rb
37
38
  - lib/l43/base/data_class/data_class_maker.rb
38
39
  - lib/l43/base/version.rb