yarrow 0.7.1 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.