yarrow 0.7.1 → 0.7.3

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.
@@ -0,0 +1,30 @@
1
+ module Yarrow
2
+ module Schema
3
+ module Definitions
4
+ DEFINED_TYPES = {
5
+ string: Type::Raw[String],
6
+ integer: Type::Raw[Integer],
7
+ path: Type::Raw[Pathname],
8
+ any: Type::Any
9
+ }
10
+
11
+ def self.register(identifier, type_class)
12
+ if DEFINED_TYPES.key?(identifier)
13
+ raise "#{identifier} is already defined"
14
+ end
15
+
16
+ DEFINED_TYPES[identifier] = type_class
17
+ end
18
+
19
+ def resolve_type(identifier)
20
+ #return identifier unless identifier.is_a?(Symbol)
21
+
22
+ unless DEFINED_TYPES.key?(identifier)
23
+ raise "#{identifier} is not defined"
24
+ end
25
+
26
+ return DEFINED_TYPES[identifier]
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,49 @@
1
+ module Yarrow
2
+ module Schema
3
+ # Specifies types plugged into each attribute slot and runs any required
4
+ # validations and coercions.
5
+ #
6
+ # Current design throws on error rather than returns a boolean result.
7
+ class Dictionary
8
+ include Definitions
9
+
10
+ # @param attrs_spec [Hash] defines the slots in the schema to validate against
11
+ def initialize(attrs_spec={})
12
+ @attrs_spec = attrs_spec.reduce({}) do |spec, (name, type_identifier)|
13
+ spec[name] = resolve_type(type_identifier)
14
+ spec
15
+ end
16
+ end
17
+
18
+ def define_attribute(name, type_identifier)
19
+ @attrs_spec[name] = resolve_type(type_identifier)
20
+ end
21
+
22
+ def attr_names
23
+ @attrs_spec.keys
24
+ end
25
+
26
+ def check(input)
27
+ missing_attrs = @attrs_spec.keys.difference(input.keys)
28
+
29
+ if missing_attrs.any?
30
+ missing_attrs.each do |name|
31
+ raise "wrong number of attributes" unless @attrs_spec[name].eql?(Type::Any)
32
+ end
33
+ end
34
+
35
+ mismatching_attrs = input.keys.difference(@attrs_spec.keys)
36
+
37
+ raise "attribute does not exist" if mismatching_attrs.any?
38
+
39
+ input.each do |(name, value)|
40
+ unless value.is_a?(@attrs_spec[name]) || @attrs_spec[name].eql?(Type::Any)
41
+ raise "wrong data type"
42
+ end
43
+ end
44
+
45
+ true
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,51 @@
1
+ module Yarrow
2
+ module Schema
3
+ # Entity with comparison by reference equality. Generates attribute helpers
4
+ # for a declared set of props. Used to replace Hashie::Mash without dragging
5
+ # in a whole new library.
6
+ class Entity
7
+ class << self
8
+ def attribute(name, value_type)
9
+ dictionary.define_attribute(name, value_type)
10
+ attr_reader(name)
11
+ end
12
+
13
+ def dictionary
14
+ @dictionary ||= Dictionary.new({})
15
+ end
16
+ end
17
+
18
+ def initialize(config)
19
+ dictionary.check(config)
20
+ # dictionary.each_key do |name|
21
+ # raise "missing declared attribute #{name}" unless config.key?(name)
22
+ # end
23
+ #
24
+ config.each_pair do |key, value|
25
+ # raise "#{key} not a declared attribute" unless dictionary.key?(key)
26
+ #
27
+ # defined_type = dictionary[key]
28
+ #
29
+ # unless value.is_a?(defined_type)
30
+ # raise "#{key} accepts #{defined_type} but #{value.class} given"
31
+ # end
32
+
33
+ instance_variable_set("@#{key}", value)
34
+ end
35
+ end
36
+
37
+ def to_h
38
+ dictionary.attr_names.reduce({}) do |attr_dict, name|
39
+ attr_dict[name] = instance_variable_get("@#{name}")
40
+ attr_dict
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def dictionary
47
+ self.class.dictionary
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,73 @@
1
+ module Yarrow
2
+ module Schema
3
+ module Types
4
+ class CastError < TypeError
5
+ def self.instance_of(t, u)
6
+ new("#{t} is not an instance of #{u}")
7
+ end
8
+
9
+ def self.kind_of(t, u)
10
+ new("#{t} is not a subclass of #{u}")
11
+ end
12
+ end
13
+
14
+ class TypeClass
15
+ attr_reader :unit
16
+
17
+ def initialize(unit=nil)
18
+ @unit = unit
19
+ end
20
+
21
+ def check_instance_of!(input)
22
+ unless input.instance_of?(unit)
23
+ raise CastError.instance_of(input.class, unit)
24
+ end
25
+ end
26
+
27
+ def check_kind_of!(input)
28
+ unless input.kind_of?(unit)
29
+ raise CastError.kind_of(input.class, unit)
30
+ end
31
+ end
32
+
33
+ def check_respond_to!(input)
34
+
35
+ end
36
+
37
+ def cast(input); end
38
+ end
39
+
40
+ class Any < TypeClass
41
+ def cast(input)
42
+ input
43
+ end
44
+ end
45
+
46
+ class Instance < TypeClass
47
+ def cast(input)
48
+ check_instance_of!(input)
49
+ input
50
+ end
51
+ end
52
+
53
+ class Kind
54
+ def cast(input)
55
+ check_kind_of!(input)
56
+ input
57
+ end
58
+ end
59
+
60
+ class Interface
61
+
62
+ end
63
+
64
+ class Optional
65
+
66
+ end
67
+
68
+ class Constrained
69
+
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,46 @@
1
+ module Yarrow
2
+ module Schema
3
+ # Value object (with comparison by value equality). This just chucks back a
4
+ # Ruby struct but wraps the constructor with method advice that handles
5
+ # type checking and conversion.
6
+ class Value
7
+ def self.new(*slots, **fields, &block)
8
+ factory(*slots, **fields, &block)
9
+ end
10
+
11
+ def self.factory(*slots, **fields, &block)
12
+ if slots.empty? && fields.empty?
13
+ raise ArgumentError.new("missing attribute definition")
14
+ end
15
+
16
+ slots_spec, fields_spec = if fields.any?
17
+ raise ArgumentError.new("cannot use slots when field map is supplied") if slots.any?
18
+ [fields.keys, fields]
19
+ else
20
+ [slots, Hash[slots.map { |s| [s, :any]}]]
21
+ end
22
+
23
+ validator = Dictionary.new(fields_spec)
24
+
25
+ struct = Struct.new(*slots_spec, keyword_init: true, &block)
26
+
27
+ struct.define_method :initialize do |*args, **kwargs|
28
+ attr_values = if args.any?
29
+ raise ArgumentError.new("cannot mix slots and kwargs") if kwargs.any?
30
+ Hash[slots.zip(args)]
31
+ else
32
+ kwargs
33
+ end
34
+
35
+ validator.check(attr_values)
36
+ # TODO: type coercion or mapping decision goes here
37
+ super(**attr_values)
38
+
39
+ freeze
40
+ end
41
+
42
+ struct
43
+ end
44
+ end
45
+ end
46
+ end
data/lib/yarrow/schema.rb CHANGED
@@ -1,132 +1,41 @@
1
+ require "delegate"
2
+
1
3
  module Yarrow
2
4
  module Schema
3
5
  module Type
4
- class Any
5
- end
6
- end
7
-
8
- ##
9
- # Checks values plugged into each slot and runs any required validations
10
- # (validations not yet implemented).
11
- #
12
- # Current design throws on error rather than returns a boolean result.
13
- class Validator
14
- # @param fields_spec [Hash] defines the slots in the schema to validate against
15
- def initialize(fields_spec)
16
- @spec = fields_spec
17
- end
18
-
19
- def check(fields)
20
- missing_fields = @spec.keys.difference(fields.keys)
21
-
22
- if missing_fields.any?
23
- missing_fields.each do |field|
24
- raise "wrong number of args" unless @spec[field].eql?(Type::Any)
25
- end
26
- end
27
-
28
- mismatching_fields = fields.keys.difference(@spec.keys)
29
-
30
- raise "key does not exist" if mismatching_fields.any?
31
-
32
- fields.each do |(field, value)|
33
- raise "wrong data type" unless value.is_a?(@spec[field]) || @spec[field].eql?(Type::Any)
34
- end
35
-
36
- true
37
- end
38
- end
39
-
40
- ##
41
- # Value object (with comparison by value equality). This just chucks back a
42
- # Ruby struct but wraps the constructor with method advice that handles
43
- # validation (and eventually type coercion if !yagni).
44
- class Value
45
- def self.new(*slots, **fields, &block)
46
- factory(*slots, **fields, &block)
47
- end
48
-
49
- def self.factory(*slots, **fields, &block)
50
- if slots.empty? && fields.empty?
51
- raise ArgumentError.new("missing attribute definition")
52
- end
53
-
54
- slots_spec, fields_spec = if fields.any?
55
- raise ArgumentError.new("cannot use slots when field map is supplied") if slots.any?
56
- [fields.keys, fields]
57
- else
58
- [slots, Hash[slots.map { |s| [s, Type::Any]}]]
59
- end
60
-
61
- validator = Validator.new(fields_spec)
62
-
63
- struct = Struct.new(*slots_spec, keyword_init: true, &block)
64
-
65
- struct.define_method :initialize do |*args, **kwargs|
66
- attr_values = if args.any?
67
- raise ArgumentError.new("cannot mix slots and kwargs") if kwargs.any?
68
- Hash[slots.zip(args)]
69
- else
70
- kwargs
6
+ class Raw
7
+ class << self
8
+ def [](primitive)
9
+ @primitive = primitive
71
10
  end
72
11
 
73
- validator.check(attr_values)
74
- # TODO: type coercion or mapping decision goes here
75
- super(**attr_values)
76
-
77
- freeze
78
- end
79
-
80
- struct
81
- end
82
- end
83
-
84
- ##
85
- # Entity with comparison by reference equality. Generates attribute helpers
86
- # for a declared set of props. Used to replace Hashie::Mash without dragging
87
- # in a whole new library.
88
- class Entity
89
- class << self
90
- def attribute(name, value_type)
91
- # define_method("map_#{name}".to_sym) do |input|
92
- # value_type.coerce(input)
93
- # end
94
- dictionary[name] = value_type
95
- attr_reader(name)
96
- end
97
-
98
- def dictionary
99
- @dictionary ||= Hash.new
100
- end
101
- end
102
-
103
- def dictionary
104
- self.class.dictionary
105
- end
106
-
107
- def initialize(config)
108
- dictionary.each_key do |name|
109
- raise "missing declared attribute #{name}" unless dictionary.key?(name)
110
- end
111
-
112
- config.each_pair do |key, value|
113
- raise "#{key} not a declared attribute" unless dictionary.key?(key)
114
-
115
- defined_type = dictionary[key]
116
-
117
- unless value.is_a?(defined_type)
118
- raise "#{key} accepts #{defined_type} but #{value.class} given"
12
+ def new(input)
13
+ input
119
14
  end
120
-
121
- instance_variable_set("@#{key}", value)
122
15
  end
123
16
  end
124
- end
125
17
 
126
- def to_h
127
- dictionary.keys.reduce({}) do |h, name|
128
- h[name] = instance_variable_get("@#{name}")
18
+ class Any
129
19
  end
20
+ # class Attribute
21
+ # class << self
22
+ # def accepts(attr_type)
23
+ # @accepts = attr_type
24
+ # end
25
+ # end
26
+ #
27
+ # attr_accessor :value
28
+ # alias_method :__getobj__, :value
29
+ #
30
+ # def initialize(value)
31
+ # raise "Invalid type" unless @accepts.is_a?(value.class)
32
+ # @value = value
33
+ # end
34
+ # end
35
+ #
36
+ # class Text < Attribute
37
+ # accepts String
38
+ # end
130
39
  end
131
40
  end
132
41
  end
@@ -3,15 +3,30 @@ require "strings-case"
3
3
 
4
4
  module Yarrow
5
5
  module Symbols
6
+ # @param [Array<String>, Array<Symbol>] parts
7
+ # @return [Object]
8
+ def self.to_module_const(parts)
9
+ Object.const_get(parts.map { |atom|
10
+ Strings::Case.pascalcase(atom.to_s)
11
+ }.join("::"))
12
+ end
13
+
6
14
  # Converts an atomic content identifier to a live class constant.
15
+ #
16
+ # @param [Symbol, String] atom
17
+ # @return [Object]
7
18
  def self.to_const(atom)
8
19
  Object.const_get(Strings::Case.pascalcase(atom.to_s).to_sym)
9
20
  end
10
21
 
22
+ # @param [Symbol, String] atom
23
+ # @return [Symbol]
11
24
  def self.to_singular(atom)
12
25
  Strings::Inflection.singularize(atom.to_s).to_sym
13
26
  end
14
27
 
28
+ # @param [Symbol, String] atom
29
+ # @return [Symbol]
15
30
  def self.to_plural(atom)
16
31
  Strings::Inflection.pluralize(atom.to_s).to_sym
17
32
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module Yarrow
3
3
  APP_NAME = 'Yarrow'
4
- VERSION = '0.7.1'
4
+ VERSION = '0.7.3'
5
5
  end
data/lib/yarrow.rb CHANGED
@@ -6,20 +6,29 @@ require 'yarrow/extensions'
6
6
  require 'yarrow/symbols'
7
7
  require 'yarrow/logging'
8
8
  require 'yarrow/schema'
9
+ require 'yarrow/schema/types'
10
+ require 'yarrow/schema/definitions'
11
+ require 'yarrow/schema/dictionary'
12
+ require 'yarrow/schema/entity'
13
+ require 'yarrow/schema/value'
9
14
  require 'yarrow/config'
10
15
  require 'yarrow/configuration'
11
16
  require 'yarrow/console_runner'
12
- require 'yarrow/generator'
13
17
  require 'yarrow/tools/front_matter'
14
18
  require 'yarrow/tools/content_utils'
15
19
  require 'yarrow/content/graph'
16
- require 'yarrow/content/content_type'
17
20
  require 'yarrow/content/source'
18
- require 'yarrow/content/source_collector'
19
- require 'yarrow/content/collection_expander'
21
+ require 'yarrow/content/expansion'
22
+ require 'yarrow/content/expansion_strategy'
23
+ require 'yarrow/content/tree_expansion'
24
+ require 'yarrow/content/manifest'
25
+ require 'yarrow/content/resource'
26
+ require 'yarrow/content/model'
27
+ require 'yarrow/content/policy'
20
28
  require 'yarrow/output/mapper'
21
29
  require 'yarrow/output/generator'
22
30
  require 'yarrow/output/context'
31
+ require 'yarrow/output/result'
23
32
  require 'yarrow/output/web/indexed_file'
24
33
  require 'yarrow/content_map'
25
34
  require 'yarrow/server'
@@ -31,6 +40,8 @@ require 'yarrow/process/expand_content'
31
40
  require 'yarrow/process/extract_source'
32
41
  require 'yarrow/process/project_manifest'
33
42
 
43
+ require 'yarrow/generator'
44
+
34
45
  # Dir[File.dirname(__FILE__) + '/yarrow/generators/*.rb'].each do |generator|
35
46
  # require generator
36
47
  # end
data/yarrow.gemspec CHANGED
@@ -20,9 +20,9 @@ Gem::Specification.new do |spec|
20
20
  spec.add_runtime_dependency 'em-websocket', '~> 0.5.1'
21
21
  spec.add_runtime_dependency 'strings-inflection', '~> 0.1'
22
22
  spec.add_runtime_dependency 'strings-case', '~> 0.3'
23
- spec.add_development_dependency 'bundler', '~> 2.2.9'
23
+ spec.add_runtime_dependency 'kramdown', '~> 2.4.0'
24
24
  spec.add_development_dependency 'rake', '~> 13.0'
25
- spec.add_development_dependency 'rspec', '~> 3.10'
25
+ spec.add_development_dependency 'rspec', '~> 3.11'
26
26
  spec.add_development_dependency 'coveralls', '~> 0.8.23'
27
27
  spec.add_development_dependency 'rack-test', '~> 0.8'
28
28
  spec.homepage = 'http://rubygemspec.org/gems/yarrow'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yarrow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Rickerby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-31 00:00:00.000000000 Z
11
+ date: 2022-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mementus
@@ -109,19 +109,19 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.3'
111
111
  - !ruby/object:Gem::Dependency
112
- name: bundler
112
+ name: kramdown
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 2.2.9
118
- type: :development
117
+ version: 2.4.0
118
+ type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 2.2.9
124
+ version: 2.4.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rake
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '3.10'
145
+ version: '3.11'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '3.10'
152
+ version: '3.11'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: coveralls
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -203,11 +203,15 @@ files:
203
203
  - lib/yarrow/config.rb
204
204
  - lib/yarrow/configuration.rb
205
205
  - lib/yarrow/console_runner.rb
206
- - lib/yarrow/content/collection_expander.rb
207
- - lib/yarrow/content/content_type.rb
206
+ - lib/yarrow/content/expansion.rb
207
+ - lib/yarrow/content/expansion_strategy.rb
208
208
  - lib/yarrow/content/graph.rb
209
+ - lib/yarrow/content/manifest.rb
210
+ - lib/yarrow/content/model.rb
211
+ - lib/yarrow/content/policy.rb
212
+ - lib/yarrow/content/resource.rb
209
213
  - lib/yarrow/content/source.rb
210
- - lib/yarrow/content/source_collector.rb
214
+ - lib/yarrow/content/tree_expansion.rb
211
215
  - lib/yarrow/content_map.rb
212
216
  - lib/yarrow/defaults.yml
213
217
  - lib/yarrow/extensions.rb
@@ -217,6 +221,7 @@ files:
217
221
  - lib/yarrow/output/context.rb
218
222
  - lib/yarrow/output/generator.rb
219
223
  - lib/yarrow/output/mapper.rb
224
+ - lib/yarrow/output/result.rb
220
225
  - lib/yarrow/output/web/indexed_file.rb
221
226
  - lib/yarrow/process/expand_content.rb
222
227
  - lib/yarrow/process/extract_source.rb
@@ -224,9 +229,14 @@ files:
224
229
  - lib/yarrow/process/step_processor.rb
225
230
  - lib/yarrow/process/workflow.rb
226
231
  - lib/yarrow/schema.rb
232
+ - lib/yarrow/schema/definitions.rb
233
+ - lib/yarrow/schema/dictionary.rb
234
+ - lib/yarrow/schema/entity.rb
235
+ - lib/yarrow/schema/types.rb
227
236
  - lib/yarrow/schema/validations/array.rb
228
237
  - lib/yarrow/schema/validations/object.rb
229
238
  - lib/yarrow/schema/validations/string.rb
239
+ - lib/yarrow/schema/value.rb
230
240
  - lib/yarrow/server.rb
231
241
  - lib/yarrow/server/livereload.rb
232
242
  - lib/yarrow/source/graph.rb
@@ -258,7 +268,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
258
268
  - !ruby/object:Gem::Version
259
269
  version: '0'
260
270
  requirements: []
261
- rubygems_version: 3.1.2
271
+ rubygems_version: 3.3.7
262
272
  signing_key:
263
273
  specification_version: 4
264
274
  summary: Documentation generator based on a fluent data model.