yaml_normalizer 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d872c2e4bbddcde16c368ddd2279ad2b1a5a6f85
4
+ data.tar.gz: 0b2f989dfbc4c0be5250f3afffc8fa654703462f
5
+ SHA512:
6
+ metadata.gz: ca1c6808fc72ce7354a192ff7addc18d0d5fbf409ca030790da5f096977057785aa174307a89ebca66ad744801556895635118df0e7dbce6d20126f1289b72d2
7
+ data.tar.gz: 9a3c8646211ecc2279b99f36688f99540115d57d0cb2dfbb707d026346ba671c0b27499ff1e5a5b5675f2ef0cb4cdec2bfdee10e8e123e61fb4cbd58524fcb9f
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'yaml_normalizer'
5
+
6
+ YamlNormalizer::Services::Normalize.call(*ARGV)
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml_normalizer'
4
+
5
+ module YamlNormalizer
6
+ # Provides Rake task integration
7
+ class RakeTask < ::Rake::TaskLib
8
+ # @return [String] name of the Rake task
9
+ attr_accessor :name
10
+ # @return [Array] arguments to be passed to Suggest.run
11
+ attr_accessor :args
12
+
13
+ # @param name [String] name of the Rake task
14
+ # @param *args [Array] arguments to be passed to Normalize.call
15
+ # @param &block [Proc] optional, evaluated inside the task definition
16
+ def initialize(name = 'yaml_normalizer', *args, &block)
17
+ @name = name
18
+ @args = args
19
+ yield(self) if block
20
+
21
+ desc 'Normalize all YAML files in path'
22
+ task(@name) { normalize }
23
+ end
24
+
25
+ # @return [void]
26
+ def normalize
27
+ ::YamlNormalizer::Services::Normalize.call('**/*')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlNormalizer
4
+ module Refinements
5
+ # Refine Hash to add method sort_by_key
6
+ module HashNamespaced
7
+ refine Hash do
8
+ # Transforms a tree-shaped hash into a plain key-value pair hash,
9
+ # separating tree levels with a dot.
10
+ # @examples
11
+ # {a: {b: {c: 1}}, b:{x: 2, y: {ok: true}, z: 4}}.namespaced
12
+ # => {"a.b.c"=>1, "b.x"=>2, "b.y.ok"=>true, "b.z"=>4}
13
+ def namespaced(namespace = [], tree = {})
14
+ each do |key, value|
15
+ child_ns = namespace.dup << key
16
+ if value.is_a?(Hash)
17
+ value.namespaced child_ns, tree
18
+ else
19
+ tree[child_ns.join('.')] = value
20
+ end
21
+ end
22
+ tree
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ # mutant doen't support Refinements use monky-patch for mutation testing
30
+ # class Hash
31
+ # # Transforms a tree-shaped hash into a plain key-value pair hash,
32
+ # # separating tree levels with a dot.
33
+ # # @examples
34
+ # # {a: {b: {c: 1}}, b:{x: 2, y: {ok: true}, z: 4}}.namespaced
35
+ # # => {"a.b.c"=>1, "b.x"=>2, "b.y.ok"=>true, "b.z"=>4}
36
+ # def namespaced(namespace = [], tree = {})
37
+ # each do |key, value|
38
+ # child_ns = namespace.dup << key
39
+ # if value.is_a?(Hash)
40
+ # value.namespaced child_ns, tree
41
+ # else
42
+ # tree[child_ns.join('.')] = value
43
+ # end
44
+ # end
45
+ # tree
46
+ # end
47
+ # end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlNormalizer
4
+ module Refinements
5
+ # Refine Hash to add method sort_by_key
6
+ module HashSortByKey
7
+ refine Hash do
8
+ # Sorts entries alphabetically by key and returns a new Hash
9
+ # sort_by_key does not modify the Hash it's called on.
10
+ def sort_by_key(recursive = true, &block)
11
+ keys.sort(&block).each_with_object({}) do |key, seed|
12
+ seed[key] = self[key]
13
+ if recursive && seed[key].is_a?(Hash)
14
+ seed[key] = seed[key].sort_by_key(true, &block)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # mutant doen't support Refinements use monky-patch for mutation testing
24
+ # class Hash
25
+ # # Sorts entries alphabetically by key and returns a new Hash
26
+ # # sort_by_key does not modify the Hash it's called on.
27
+ # def sort_by_key(recursive = true, &block)
28
+ # keys.sort(&block).each_with_object({}) do |key, seed|
29
+ # seed[key] = self[key]
30
+ # if recursive && seed[key].is_a?(Hash)
31
+ # seed[key] = seed[key].sort_by_key(true, &block)
32
+ # end
33
+ # end
34
+ # end
35
+ # end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlNormalizer
4
+ # Refinements holds all refinements used for Yaml Normalizer
5
+ module Refinements
6
+ end
7
+ end
8
+
9
+ require 'yaml_normalizer/refinements/hash_sort_by_key'
10
+ require 'yaml_normalizer/refinements/hash_namespaced'
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlNormalizer
4
+ module Services
5
+ # The Base Service provides a convenience class method "call" to initialize
6
+ # the Service with the given arguments and call the method "call" on the
7
+ # instance.
8
+ class Base
9
+ # A convenience class method to initialize Normalize with the given
10
+ # arguments and call the method "call" on the instance.
11
+ def self.call(*args)
12
+ new(*args).call
13
+ end
14
+
15
+ # Inherit from Base and implement the call method
16
+ def call
17
+ raise NotImplementedError
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'psych'
4
+
5
+ module YamlNormalizer
6
+ module Services
7
+ # describe!
8
+ class IsYaml < Base
9
+ attr_reader :file
10
+
11
+ def initialize(file)
12
+ @file = file.to_s
13
+ end
14
+
15
+ # Return true if given file is a valid YAML file
16
+ def call
17
+ file? && parsable? && !scalar?
18
+ end
19
+
20
+ private
21
+
22
+ def file?
23
+ File.file? file
24
+ end
25
+
26
+ # The current implementation does not require parsable? to return a
27
+ # boolean value
28
+ def parsable?
29
+ Psych.load_file(file)
30
+ rescue Psych::SyntaxError
31
+ false
32
+ end
33
+
34
+ def scalar?
35
+ Psych.load_file(file).instance_of? String
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'peach'
4
+
5
+ module YamlNormalizer
6
+ module Services
7
+ # Normalize is a Service that provides functionality to
8
+ class Normalize < Base
9
+ attr_reader :files
10
+
11
+ using YamlNormalizer::Refinements::HashSortByKey
12
+ using YamlNormalizer::Refinements::HashNamespaced
13
+
14
+ def initialize(*args)
15
+ files = args.each_with_object([]) { |a, o| o << Dir[a.to_s] }
16
+ @files = files.flatten.sort.uniq
17
+ end
18
+
19
+ # Normalizes all YAML files defined on instantiation.
20
+ def call
21
+ files.peach do |file|
22
+ if IsYaml.call(file)
23
+ normalize!(file)
24
+ else
25
+ $stderr.puts "#{file} not a YAML file"
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def normalize!(file)
33
+ if stable?(input = File.read(file), norm = normalize_yaml(input))
34
+ File.open(file, 'w') { |f| f.write(norm) }
35
+ $stderr.puts "[NORMALIZED] #{file}"
36
+ else
37
+ $stderr.puts "[ERROR] Could not normalize #{file}"
38
+ end
39
+ end
40
+
41
+ def normalize_yaml(yaml)
42
+ hashes = Psych.parse_stream(yaml).transform
43
+ hashes.map(&:sort_by_key).map(&:to_yaml).join
44
+ end
45
+
46
+ def stable?(yaml_a, yaml_b)
47
+ parse(yaml_a).each_with_index.all? do |a, i|
48
+ a.namespaced.eql?(parse(yaml_b).fetch(i).namespaced)
49
+ end
50
+ end
51
+
52
+ def parse(yaml)
53
+ Psych.parse_stream(yaml).transform
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlNormalizer
4
+ # Holds all Yaml Normalizer services
5
+ module Services
6
+ end
7
+ end
8
+
9
+ require 'yaml_normalizer/services/base'
10
+ require 'yaml_normalizer/services/is_yaml'
11
+ require 'yaml_normalizer/services/normalize'
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlNormalizer
4
+ # The current Yaml Normalizer version
5
+ VERSION = '0.1.0'
6
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Yaml Normalizer normalizes YAML files ensuring Psych's parsing result of
4
+ # the YAML file is identical before and after normalization.
5
+ module YamlNormalizer
6
+ end
7
+
8
+ require 'yaml_normalizer/version'
9
+ require 'yaml_normalizer/refinements'
10
+ require 'yaml_normalizer/services'
metadata ADDED
@@ -0,0 +1,370 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yaml_normalizer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Wolfgang Teuber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: psych
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: peach
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: parallel_tests
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: mutant-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: cane
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: flay
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: flog
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: inch
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: coveralls
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: guard
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: guard-rubocop
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: guard-rspec
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
237
+ - !ruby/object:Gem::Dependency
238
+ name: yard
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :development
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
251
+ - !ruby/object:Gem::Dependency
252
+ name: redcarpet
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ version: '0'
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ">="
263
+ - !ruby/object:Gem::Version
264
+ version: '0'
265
+ - !ruby/object:Gem::Dependency
266
+ name: github-markup
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - ">="
270
+ - !ruby/object:Gem::Version
271
+ version: '0'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - ">="
277
+ - !ruby/object:Gem::Version
278
+ version: '0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: awesome_print
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: '0'
293
+ - !ruby/object:Gem::Dependency
294
+ name: pry
295
+ requirement: !ruby/object:Gem::Requirement
296
+ requirements:
297
+ - - ">="
298
+ - !ruby/object:Gem::Version
299
+ version: '0'
300
+ type: :development
301
+ prerelease: false
302
+ version_requirements: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - ">="
305
+ - !ruby/object:Gem::Version
306
+ version: '0'
307
+ - !ruby/object:Gem::Dependency
308
+ name: pry-byebug
309
+ requirement: !ruby/object:Gem::Requirement
310
+ requirements:
311
+ - - ">="
312
+ - !ruby/object:Gem::Version
313
+ version: '0'
314
+ type: :development
315
+ prerelease: false
316
+ version_requirements: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - ">="
319
+ - !ruby/object:Gem::Version
320
+ version: '0'
321
+ description: |-
322
+ Yaml Normalizer follows the notion that there is
323
+ a normalized YAML file format. It re-formats YAML files in a way that the
324
+ results closely match Psych's output. Yaml Normalizer ensures that the
325
+ original file and the resulting file are 100% identical to Psych (stable
326
+ change).
327
+ email:
328
+ - wolfgang.teuber@sage.com
329
+ executables:
330
+ - yaml_normalizer
331
+ extensions: []
332
+ extra_rdoc_files: []
333
+ files:
334
+ - bin/yaml_normalizer
335
+ - lib/yaml_normalizer.rb
336
+ - lib/yaml_normalizer/rake_task.rb
337
+ - lib/yaml_normalizer/refinements.rb
338
+ - lib/yaml_normalizer/refinements/hash_namespaced.rb
339
+ - lib/yaml_normalizer/refinements/hash_sort_by_key.rb
340
+ - lib/yaml_normalizer/services.rb
341
+ - lib/yaml_normalizer/services/base.rb
342
+ - lib/yaml_normalizer/services/is_yaml.rb
343
+ - lib/yaml_normalizer/services/normalize.rb
344
+ - lib/yaml_normalizer/version.rb
345
+ homepage: https://github.com/Sage/yaml_normalizer
346
+ licenses:
347
+ - MIT
348
+ metadata: {}
349
+ post_install_message:
350
+ rdoc_options: []
351
+ require_paths:
352
+ - lib
353
+ required_ruby_version: !ruby/object:Gem::Requirement
354
+ requirements:
355
+ - - ">="
356
+ - !ruby/object:Gem::Version
357
+ version: '0'
358
+ required_rubygems_version: !ruby/object:Gem::Requirement
359
+ requirements:
360
+ - - ">="
361
+ - !ruby/object:Gem::Version
362
+ version: '0'
363
+ requirements: []
364
+ rubyforge_project:
365
+ rubygems_version: 2.6.8
366
+ signing_key:
367
+ specification_version: 4
368
+ summary: Yaml Normalizer normalizes YAML files
369
+ test_files: []
370
+ has_rdoc: