openapi-sourcetools 0.7.1 → 0.8.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.
data/lib/docs.rb DELETED
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright © 2024 Ismo Kärkkäinen
4
- # Licensed under Universal Permissive License. See LICENSE.txt.
5
-
6
- require_relative 'common'
7
-
8
-
9
- class Docs
10
- attr_reader :docs
11
-
12
- def initialize
13
- @docs = {}
14
- end
15
-
16
- def method_missing(method_name, *args)
17
- name = method_name.to_s
18
- if name.end_with?('=')
19
- name = name[0...(name.size - 1)]
20
- super unless @docs.key?(name)
21
- @docs[name] = args.first
22
- return args.first
23
- end
24
- super unless @docs.key?(name)
25
- @docs[name]
26
- end
27
-
28
- def add(name, content)
29
- return false if docs.key?(name)
30
- @docs[name] = content
31
- true
32
- end
33
- end
data/lib/generate.rb DELETED
@@ -1,90 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # Copyright © 2024 Ismo Kärkkäinen
5
- # Licensed under Universal Permissive License. See LICENSE.txt.
6
-
7
- require_relative 'common'
8
- require_relative 'loaders'
9
- require_relative 'gen'
10
-
11
-
12
- def executable_bits_on(mode)
13
- mode = mode.to_s(8).split('')
14
- mode.size.times do |k|
15
- m = mode[k].to_i(8)
16
- # Applies to Unix-likes. Other system, check and handle.
17
- m += 1 unless 3 < mode.size - k || m.zero? || m % 2 == 1
18
- mode[k] = m
19
- end
20
- m = 0
21
- mode.each do |v|
22
- m = 8 * m + v
23
- end
24
- m
25
- end
26
-
27
- class Generator
28
- def initialize(document_content, input_name, output_directory)
29
- Gen.setup(document_content, input_name, output_directory)
30
- Gen.loaders = Loaders.loaders
31
- end
32
-
33
- def context_binding
34
- binding
35
- end
36
-
37
- def load(generator_names)
38
- generator_names.each do |name|
39
- idx = Gen.loaders.index { |loader| loader.call(name) }
40
- return aargh("No loader could handle #{name}", 2) if idx.nil?
41
- end
42
- 0
43
- rescue StandardError => e
44
- aargh(e.to_s, 2)
45
- end
46
-
47
- def generate(t)
48
- t.generate(context_binding)
49
- rescue Exception => e
50
- aargh(e.to_s, 4)
51
- end
52
-
53
- def output_name(t, index)
54
- name = t.output_name
55
- name = "#{index}.txt" if name.nil?
56
- File.join(Gen.outdir, name)
57
- end
58
-
59
- def save(name, contents, executable)
60
- f = File.new(name, File::WRONLY | File::CREAT | File::TRUNC)
61
- s = executable ? f.stat : nil
62
- f.write(contents)
63
- f.close
64
- return unless executable
65
- mode = executable_bits_on(s.mode)
66
- File.chmod(mode, name) unless mode == s.mode
67
- end
68
-
69
- def run
70
- # This allows tasks to be added while processing.
71
- # Not intended to be done but might prove handy.
72
- # Also exposes current task index in case new task is added in the middle.
73
- Gen.task_index = 0
74
- while Gen.task_index < Gen.tasks.size
75
- Gen.t = Gen.tasks[Gen.task_index]
76
- out = generate(Gen.t)
77
- Gen.task_index += 1
78
- next if Gen.t.discard # Check first to ignore result if no output.
79
- return out if out.is_a?(Integer)
80
- next if out.empty? # Allows no output but return value still checked.
81
- name = output_name(Gen.t, Gen.task_index - 1)
82
- begin
83
- save(name, out, Gen.t.executable)
84
- rescue StandardError => e
85
- return aargh("Error writing output file: #{name}\n#{e}", 3)
86
- end
87
- end
88
- 0
89
- end
90
- end
data/lib/helper.rb DELETED
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright © 2024 Ismo Kärkkäinen
4
- # Licensed under Universal Permissive License. See LICENSE.txt.
5
-
6
- require_relative 'task'
7
-
8
-
9
- class Helper
10
- attr_reader :doc, :parents
11
- attr_accessor :parent_parameters
12
-
13
- # Stores the nearest Hash for each Hash.
14
- def store_parents(obj, parent = nil)
15
- if obj.is_a?(Hash)
16
- @parents[obj.object_id] = parent
17
- obj.each do |k, v|
18
- store_parents(v, obj)
19
- end
20
- elsif obj.is_a?(Array)
21
- obj.each do |v|
22
- store_parents(v, parent)
23
- end
24
- end
25
- end
26
-
27
- def initialize(doc)
28
- @doc = doc
29
- @parents = {}
30
- store_parents(@doc)
31
- end
32
-
33
- def parent(object)
34
- @parents[object.object_id]
35
- end
36
-
37
- COMPONENTS = '#/components/'
38
-
39
- def category_and_name(ref_or_obj)
40
- ref = ref_or_obj.is_a?(Hash) ? ref_or_obj['$ref'] : ref_or_obj
41
- return nil unless ref.is_a?(String)
42
- return nil unless ref.start_with?(Helper::COMPONENTS)
43
- idx = ref.index('/', Helper::COMPONENTS.size)
44
- return nil if idx.nil?
45
- category = ref[Helper::COMPONENTS.size...idx]
46
- [ category, ref[(idx + 1)...ref.size] ]
47
- end
48
-
49
- def dereference(ref_or_obj)
50
- cn = category_and_name(ref_or_obj)
51
- return nil if cn.nil?
52
- cs = @doc.dig('components', cn.first) || {}
53
- cs[cn.last]
54
- end
55
-
56
- def basename(ref_or_obj)
57
- cn = category_and_name(ref_or_obj)
58
- return nil if cn.nil?
59
- cn.last
60
- end
61
-
62
- def parameters(operation_object, empty_unless_local = false)
63
- return [] if empty_unless_local && !operation_object.key?('parameters')
64
- cps = @doc.dig('components', 'parameters') || {}
65
- uniqs = {}
66
- path_item_object = parent(operation_object)
67
- [path_item_object, operation_object].each do |p|
68
- p.fetch('parameters', []).each do |param|
69
- r = basename(param)
70
- r = cps[r] if r.is_a?(String)
71
- uniqs["#{r['name']}:#{r['in']}"] = param
72
- end
73
- end
74
- uniqs.keys.sort!.map { |k| uniqs[k] }
75
- end
76
- end
77
-
78
-
79
- class HelperTask
80
- include TaskInterface
81
-
82
- def generate(context_binding)
83
- Gen.h = Helper.new(Gen.doc)
84
- end
85
-
86
- def output_name
87
- nil
88
- end
89
-
90
- def discard
91
- true
92
- end
93
- end
94
-
data/lib/loaders.rb DELETED
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright © 2024 Ismo Kärkkäinen
4
- # Licensed under Universal Permissive License. See LICENSE.txt.
5
-
6
-
7
- # Original loader functions. These are accessible via Gen.loaders. New loaders
8
- # should be added there.
9
- module Loaders
10
-
11
- GEM_PREFIX = 'gem:'
12
-
13
- def self.gem_loader(name)
14
- return false unless name.downcase.start_with?(GEM_PREFIX)
15
- begin
16
- require(name.slice(GEM_PREFIX.size...name.size))
17
- rescue LoadError => e
18
- raise StandardError, "Failed to require #{name}\n#{e.to_s}"
19
- rescue Exception => e
20
- raise StandardError, "Problem with #{name}\n#{e.to_s}"
21
- end
22
- true
23
- end
24
-
25
- RUBY_EXT = '.rb'
26
-
27
- def self.ruby_loader(name)
28
- return false unless name.downcase.end_with?(RUBY_EXT)
29
- origwd = Dir.pwd
30
- d = File.dirname(name)
31
- Dir.chdir(d) unless d == '.'
32
- begin
33
- require(File.join(Dir.pwd, File.basename(name)))
34
- rescue LoadError => e
35
- raise StandardError, "Failed to require #{name}\n#{e.to_s}"
36
- rescue Exception => e
37
- raise StandardError, "Problem with #{name}\n#{e.to_s}"
38
- end
39
- Dir.chdir(origwd) unless d == '.'
40
- true
41
- end
42
-
43
- YAML_PREFIX = 'yaml:'
44
- YAML_EXTS = [ '.yaml', '.yml' ]
45
-
46
- def self.yaml_loader(name)
47
- d = name.downcase
48
- if d.start_with?(YAML_PREFIX)
49
- name = name.slice(YAML_PREFIX.size...name.size)
50
- else
51
- return false if (YAML_EXTS.index { |s| d.end_with?(s) }).nil?
52
- end
53
- n, sep, f = name.partition(':')
54
- raise StandardError, "No name given." if n.empty?
55
- raise StandardError, "No filename given." if f.empty?
56
- doc = YAML.safe_load(File.read(f))
57
- raise StandardError, "#{name} #{n} exists already." unless Gen.d.add(n, doc)
58
- true
59
- rescue Errno::ENOENT
60
- raise StandardError, "Not found: #{f}\n#{e.to_s}"
61
- rescue Exception => e
62
- raise StandardError, "Failed to read as YAML: #{f}\n#{e.to_s}"
63
- end
64
-
65
- BIN_PREFIX = 'bin:'
66
-
67
- def self.bin_loader(name)
68
- return false unless name.downcase.start_with?(BIN_PREFIX)
69
- n, sep, f = name.slice(BIN_PREFIX.size...name.size).partition(':')
70
- raise StandardError, "No name given." if n.empty?
71
- raise StandardError, "No filename given." if f.empty?
72
- doc = IO.binread(f)
73
- raise StandardError, "#{name} #{n} exists already." unless Gen.d.add(n, doc)
74
- true
75
- rescue Errno::ENOENT
76
- raise StandardError, "Not found: #{f}\n#{e.to_s}"
77
- rescue Exception => e
78
- raise StandardError, "Failed to read #{f}\n#{e.to_s}"
79
- end
80
-
81
- def self.loaders
82
- pre = @preloaders
83
- [ method(:gem_loader), method(:ruby_loader), method(:yaml_loader), method(:bin_loader) ]
84
- end
85
-
86
- def self.document
87
- %(
88
- - #{Loaders::GEM_PREFIX}gem_name : requires the gem.
89
- - ruby_file#{Loaders::RUBY_EXT} : changes to Ruby file directory and requires the file.
90
- - #{Loaders::YAML_PREFIX}name:filename : Loads YAML file into Gen.d.name.
91
- - name:filename.{#{(Loaders::YAML_EXTS.map { |s| s[1...s.size] }).join('|')}} : Loads YAML file into Gen.d.name.
92
- - #{Loaders::BIN_PREFIX}name:filename : Loads binary file into Gen.d.name.
93
- )
94
- end
95
-
96
- end
data/lib/output.rb DELETED
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright © 2024 Ismo Kärkkäinen
4
- # Licensed under Universal Permissive License. See LICENSE.txt.
5
-
6
- require_relative 'task'
7
-
8
-
9
- class Output
10
- # For indentation.
11
- attr_accessor :indent_character, :indent_step
12
- attr_accessor :tab, :tab_replaces_count
13
- attr_accessor :last_indent
14
-
15
- def initialize
16
- @indent_character = ' '
17
- @indent_step = 4
18
- @tab = "\t"
19
- @tab_replaces_count = 0
20
- @last_indent = 0
21
- end
22
-
23
- def join(blocks, separator = "\n")
24
- indented = []
25
- blocks.flatten!
26
- indent = 0
27
- blocks.each do |block|
28
- if block.nil?
29
- indent = 0
30
- elsif block.is_a?(Integer)
31
- indent += block
32
- elsif block.is_a?(TrueClass)
33
- indent += @indent_step
34
- elsif block.is_a?(FalseClass)
35
- indent -= @indent_step
36
- else
37
- block = block.to_s unless block.is_a?(String)
38
- if indent.zero?
39
- indented.push(block)
40
- next
41
- end
42
- if 0 < @tab_replaces_count
43
- tabs = @tab * (indent / @tab_replaces_count)
44
- chars = @indent_character * (indent % @tab_replaces_count)
45
- else
46
- tabs = ''
47
- chars = @indent_character * indent
48
- end
49
- lines = block.lines(chomp: true)
50
- lines.each do |line|
51
- indented.push("#{tabs}#{chars}#{line}")
52
- end
53
- end
54
- end
55
- @last_indent = indent
56
- indented.join(separator)
57
- end
58
- end
data/lib/task.rb DELETED
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright © 2024 Ismo Kärkkäinen
4
- # Licensed under Universal Permissive License. See LICENSE.txt.
5
-
6
- require 'erb'
7
- require_relative 'common'
8
-
9
-
10
- module TaskInterface
11
- def generate(context_binding)
12
- raise NotImplementedError
13
- end
14
-
15
- def output_name
16
- raise NotImplementedError
17
- end
18
-
19
- def discard
20
- false
21
- end
22
-
23
- def executable
24
- false
25
- end
26
- end
27
-
28
- class Task
29
- include TaskInterface
30
-
31
- attr_reader :src, :template, :template_name
32
- attr_accessor :name, :executable, :discard, :x
33
-
34
- def initialize(src, template, template_name)
35
- @src = src
36
- @template = template
37
- @template_name = template_name
38
- if @template.nil?
39
- raise ArgumentError, "template_name or template must be given" if @template_name.nil?
40
- begin
41
- @template = File.read(@template_name)
42
- rescue Errno::ENOENT
43
- raise StandardError, "Could not load #{@template_name}"
44
- rescue StandardError => e
45
- raise StandardError, "#{e}\nFailed to read #{@template_name}"
46
- end
47
- end
48
- @name = nil
49
- @executable = false
50
- @discard = false
51
- @x = nil
52
- end
53
-
54
- # If this is overridden to perform some processing but not to produce output,
55
- # set @discard = true and return value will be ignored. No other methods are
56
- # called in that case.
57
- def internal_generate(context_binding)
58
- ERB.new(@template).result(context_binding)
59
- end
60
-
61
- # You can override this instead of internal_generate if you do not need the
62
- # exception handling.
63
- def generate(context_binding)
64
- n = @template_name.nil? ? '' : "#{@template_name} "
65
- internal_generate(context_binding)
66
- rescue SyntaxError => e
67
- aargh("Template #{n}syntax error: #{e.full_message}", 5)
68
- rescue Exception => e
69
- aargh("Template #{n}error: #{e.full_message}", 6)
70
- end
71
-
72
- # This is only called when generate produced output that is not discarded.
73
- def output_name
74
- return @name unless @name.nil?
75
- # Using template name may show where name assignment is missing.
76
- # Name assignment may also be missing in the task creation stage.
77
- return File.basename(@template_name) unless @template_name.nil?
78
- nil
79
- end
80
- end
81
-
82
- class WriteTask
83
- include TaskInterface
84
-
85
- attr_reader :name, :contents, :executable
86
-
87
- def initialize(name, contents, executable = false)
88
- raise ArgumentError, "name and contents must be given" if name.nil? || contents.nil?
89
- @name = name
90
- @contents = contents
91
- @executable = executable
92
- end
93
-
94
- def generate(context_binding)
95
- @contents
96
- end
97
-
98
- def output_name
99
- @name
100
- end
101
- end