dsl_evaluator 0.1.2 → 0.2.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: 38416a5462223f8c1b87c303e81c02d7410e76c371fde03eb03de37a9f455a90
4
- data.tar.gz: 264bb6cc47c4c02a047dea7812810b741be48eca5f6298bce98510a568b3be26
3
+ metadata.gz: 5d712162a49ab0151d9acb686bc7613b11f242a0187f95628b5617a2fe88de58
4
+ data.tar.gz: 481d6aea0a1800ad8efc46af97771b99925d69bc81231ff4673c02f01d3e0d52
5
5
  SHA512:
6
- metadata.gz: 76d9c1b745ce57961e5d8458e0037c16709617e821f43ce6ee6b4072b54cae60e117ea6a9540ee1fde97fca86276b7498a184a77fefc5cab9b8a603103e80042
7
- data.tar.gz: bc0e3ec881d84a2ef80b16b05dbbed1c3f63877a394e9027bb409372501a557af5c08b352631ece2d49e262cde1733f7b69637bb2ca1fefce29291626501b84c
6
+ metadata.gz: '0854ffb84d518b498c2c32ddc16cfa0f6306645be452574cf22e878a002959be6792bd4f7dd0ef4e1af20460ea5443f74164bdf5cbef58a8f0a6fd48429d0062'
7
+ data.tar.gz: d66dd8eaf3d9317e74227d9fef78cdfae27f6db990587b7c80a0be29ab1b2f47c2f87c83a408fccb9b59728ca55887121798473ffcefef92af2bffead1df6e38
data/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## [0.2.1] - 2022-02-25
7
+ - [#4](https://github.com/tongueroo/dsl_evaluator/pull/4) add config.select_pattern option
8
+
9
+ ## [0.2.0] - 2022-02-24
10
+ - [#3](https://github.com/tongueroo/dsl_evaluator/pull/3) major improvements: configure ability
11
+
12
+ ## [0.1.3]
13
+ - #2 fix current line number printed
14
+
6
15
  ## [0.1.2]
7
16
  - #1 get line info from error message also
8
17
 
data/README.md CHANGED
@@ -4,14 +4,22 @@ Small module to help with DSL evaluation. Notably, it produces a human-friendly
4
4
 
5
5
  ## Usage
6
6
 
7
+ Example usage:
8
+
7
9
  ```ruby
8
- require "dsl_evaluator"
9
- DslEvaluator.backtrace_reject = "lib/my_gem" # optional
10
+ DslEvaluator.configure do |config|
11
+ config.backtrace.reject_pattern = "/lib/lono"
12
+ config.logger = Lono.logger
13
+ config.on_exception = :exit
14
+ config.root = Lono.root
15
+ end
16
+
10
17
 
11
- class DslBuilder
18
+ class Dsl
19
+ include DslEvaluator
12
20
  def build
13
21
  path = "/path/to/user/provided/dsl/file.rb"
14
- evaluate_file(path)
22
+ evaluate_file(path) # from DslEvaluator module
15
23
  end
16
24
  end
17
25
  ```
@@ -6,7 +6,7 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ["Tung Nguyen"]
7
7
  spec.email = ["tongueroo@gmail.com"]
8
8
 
9
- spec.summary = "Small module to help with DSL evaluation. It produces a human-friendly backtrace error"
9
+ spec.summary = "DSL evaluation library. It produces a human-friendly backtrace error"
10
10
  spec.homepage = "https://github.com/tongueroo/dsl_evaluator"
11
11
  spec.license = "MIT"
12
12
  spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
@@ -22,5 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
24
 
25
+ spec.add_dependency "activesupport"
26
+ spec.add_dependency "memoist"
25
27
  spec.add_dependency "rainbow"
26
28
  end
@@ -0,0 +1,38 @@
1
+ module DslEvaluator
2
+ class App
3
+ extend Memoist
4
+ include Singleton
5
+
6
+ attr_reader :config
7
+ def initialize
8
+ @config = defaults
9
+ end
10
+
11
+ def defaults
12
+ config = ActiveSupport::OrderedOptions.new
13
+
14
+ config.logger = default_logger
15
+ config.logger.formatter = Logger::Formatter.new
16
+ config.logger.level = ENV['DSL_EVALUATOR_LOG_LEVEL'] || :info
17
+
18
+ config.on_exception = :raise
19
+
20
+ config.root = Dir.pwd
21
+
22
+ config.backtrace = ActiveSupport::OrderedOptions.new
23
+ config.backtrace.reject_pattern = nil # dont use .reject. Seems its used internally by ActiveSupport::OrderedOptions
24
+ config.backtrace.select_pattern = nil
25
+
26
+ config
27
+ end
28
+
29
+ def default_logger
30
+ Logger.new(ENV['DSL_EVALUATOR_LOG_PATH'] || $stderr)
31
+ end
32
+ memoize :default_logger
33
+
34
+ def configure
35
+ yield(@config)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ module DslEvaluator
2
+ class Autoloader
3
+ class Inflector < Zeitwerk::Inflector
4
+ def camelize(basename, _abspath)
5
+ map = { cli: "CLI", version: "VERSION" }
6
+ map[basename.to_sym] || super
7
+ end
8
+ end
9
+
10
+ class << self
11
+ def setup
12
+ loader = Zeitwerk::Loader.new
13
+ loader.inflector = Inflector.new
14
+ loader.push_dir(File.dirname(__dir__)) # lib
15
+ loader.log! if ENV["DSL_EVALUATOR_AUTOLOAD_LOG"]
16
+ loader.setup
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ module DslEvaluator
2
+ class Logger < ::Logger
3
+ def initialize(*args)
4
+ super
5
+ self.formatter = Formatter.new
6
+ self.level = ENV['DSL_EVALUATOR_LOG_LEVEL'] || :info # note: only respected when config.logger not set in config/app.rb
7
+ end
8
+
9
+ def format_message(severity, datetime, progname, msg)
10
+ line = if @logdev.dev == $stdout || @logdev.dev == $stderr || @logdev.dev.is_a?(StringIO)
11
+ msg # super simple format if stdout
12
+ else
13
+ super # use the configured formatter
14
+ end
15
+ line =~ /\n$/ ? line : "#{line}\n"
16
+ end
17
+
18
+ # Used to allow output to always go to stdout
19
+ def stdout(msg, newline: true)
20
+ if newline
21
+ puts msg
22
+ else
23
+ print msg
24
+ end
25
+ end
26
+
27
+ public :print
28
+ public :printf
29
+ end
30
+ end
@@ -4,16 +4,33 @@ module DslEvaluator
4
4
  @error = error
5
5
  end
6
6
 
7
- def message
8
- @error.message
9
- end
10
-
11
7
  # Prints out a user friendly task_definition error message
12
8
  def print
13
- print_source(info)
9
+ info = error_info
10
+ path = info[:path]
11
+ line_number = info[:line_number].to_i
12
+
13
+ logger.error "Error evaluating #{pretty_path(path)}".color(:red)
14
+ logger.error "Here's the line with the error:\n\n"
15
+
16
+ contents = IO.read(path)
17
+ content_lines = contents.split("\n")
18
+ context = 5 # lines of context
19
+ top, bottom = [line_number-context-1, 0].max, line_number+context-1
20
+ lpad = content_lines.size.to_s.size
21
+ content_lines[top..bottom].each_with_index do |line_content, index|
22
+ current_line = top+index+1
23
+ if current_line == line_number
24
+ printf("%#{lpad}d %s\n".color(:red), current_line, line_content)
25
+ else
26
+ printf("%#{lpad}d %s\n", current_line, line_content)
27
+ end
28
+ end
29
+
30
+ logger.info "Rerun with FULL_BACKTRACE=1 to see full backtrace" unless ENV['FULL_BACKTRACE']
14
31
  end
15
32
 
16
- def info
33
+ def error_info
17
34
  @error.message.include?("syntax") ? info_from_message : info_from_backtrace
18
35
  end
19
36
 
@@ -23,39 +40,76 @@ module DslEvaluator
23
40
  {path: path, line_number: line_number}
24
41
  end
25
42
 
43
+ # Grab info so can print out user friendly error message
44
+ #
45
+ # Backtrace lines are different for OSes:
46
+ #
47
+ # windows: "C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/terraspace-1.1.1/lib/terraspace/builder.rb:34:in `build'"
48
+ # linux: "/home/ec2-user/.rvm/gems/ruby-3.0.3/gems/terraspace-1.1.1/lib/terraspace/compiler/dsl/syntax/mod.rb:4:in `<module:Mod>'"
49
+ #
26
50
  def info_from_backtrace
27
51
  lines = @error.backtrace
52
+ if ENV['FULL_BACKTRACE']
53
+ logger.error @error.message.color(:red)
54
+ logger.error lines.join("\n")
55
+ end
28
56
 
29
- backtrace_reject = DslEvaluator.backtrace_reject
30
- lines = lines.reject { |l| l.include?(backtrace_reject) } if backtrace_reject
31
- lines = lines.reject { |l| l.include?("lib/dsl_evaluator") } # ignore internal lib/dsl_evaluator backtrace lines
57
+ lines = reject(lines)
58
+ lines = select(lines)
32
59
 
33
60
  error_info = lines.first
34
- path, line_number, _ = error_info.split(':')
61
+ parts = error_info.split(':')
62
+ windows = error_info.match(/^[a-zA-Z]:/)
63
+ path = windows ? parts[1] : parts[0]
64
+ line_number = windows ? parts[2] : parts[1]
65
+ line_number = line_number.to_i
66
+
35
67
  {path: path, line_number: line_number}
36
68
  end
37
69
 
38
- def print_source(info={})
39
- path = info[:path]
40
- line_number = info[:line_number].to_i
70
+ def reject(lines)
71
+ # Keep DslEvaluator.backtrace_reject for backwards compatibility
72
+ pattern = config.backtrace.reject_pattern || DslEvaluator.backtrace_reject
73
+ return lines unless pattern
41
74
 
42
- puts "Error evaluating #{path}:".color(:red)
43
- puts @error.message
44
- puts "Here's the line in #{path} with the error:\n\n"
75
+ lines.reject! do |l|
76
+ if pattern.is_a?(String)
77
+ l.include?(pattern)
78
+ else
79
+ l.match(pattern)
80
+ end
81
+ end
82
+ # Always ignore internal lib/dsl_evaluator backtrace lines
83
+ lines.reject { |l| l.include?("lib/dsl_evaluator") }
84
+ end
45
85
 
46
- contents = IO.read(path)
47
- content_lines = contents.split("\n")
48
- context = 5 # lines of context
49
- top, bottom = [line_number-context-1, 0].max, line_number+context-1
50
- lpad = content_lines.size.to_s.size
51
- content_lines[top..bottom].each_with_index do |line_content, index|
52
- current_line = top+index+1
53
- if current_line == line_number
54
- printf("%#{lpad}d %s\n".color(:red), line_number, line_content)
86
+ def select(lines)
87
+ pattern = config.backtrace.select_pattern
88
+ return unless pattern
89
+
90
+ lines.select do |l|
91
+ if pattern.is_a?(String)
92
+ l.include?(pattern)
55
93
  else
56
- printf("%#{lpad}d %s\n", line_number, line_content)
94
+ l.match(pattern)
57
95
  end
58
96
  end
59
97
  end
98
+
99
+ def pretty_path(path)
100
+ path.sub("#{config.root}/",'')
101
+ end
102
+
103
+ def logger
104
+ config.logger
105
+ end
106
+
107
+ def config
108
+ DslEvaluator.config
109
+ end
110
+
111
+ def message
112
+ @error.message
113
+ end
60
114
  end
61
115
  end
@@ -1,3 +1,3 @@
1
1
  module DslEvaluator
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.1"
3
3
  end
data/lib/dsl_evaluator.rb CHANGED
@@ -1,8 +1,16 @@
1
- require "dsl_evaluator/version"
2
- require "rainbow/ext/string"
1
+ require 'active_support'
2
+ require 'active_support/core_ext/class'
3
+ require 'active_support/core_ext/hash'
4
+ require 'active_support/core_ext/string'
5
+ require 'dsl_evaluator/version'
6
+ require 'memoist'
7
+ require 'rainbow/ext/string'
8
+
9
+ require "dsl_evaluator/autoloader"
10
+ DslEvaluator::Autoloader.setup
3
11
 
4
12
  module DslEvaluator
5
- autoload :Printer, "dsl_evaluator/printer"
13
+ extend Memoist
6
14
 
7
15
  class Error < StandardError; end
8
16
 
@@ -11,18 +19,30 @@ module DslEvaluator
11
19
  instance_eval(IO.read(path), path)
12
20
  rescue Exception => e
13
21
  Printer.new(e).print
14
- puts "\nFull error:"
15
- raise
22
+ case config.on_exception
23
+ when :rescue
24
+ # do nothing
25
+ when :exit
26
+ exit 1
27
+ else # :raise
28
+ raise
29
+ end
30
+ end
31
+
32
+ mattr_accessor :backtrace_reject
33
+
34
+ def logger
35
+ config.logger
16
36
  end
17
37
 
18
- @@backtrace_reject = nil
19
- def backtrace_reject
20
- @@backtrace_reject
38
+ def configure(&block)
39
+ App.instance.configure(&block)
21
40
  end
22
41
 
23
- def backtrace_reject=(v)
24
- @@backtrace_reject = v
42
+ def config
43
+ App.instance.config
25
44
  end
45
+ memoize :config
26
46
 
27
47
  extend self
28
48
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dsl_evaluator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-30 00:00:00.000000000 Z
11
+ date: 2022-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: memoist
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: rainbow
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -43,6 +71,9 @@ files:
43
71
  - bin/setup
44
72
  - dsl_evaluator.gemspec
45
73
  - lib/dsl_evaluator.rb
74
+ - lib/dsl_evaluator/app.rb
75
+ - lib/dsl_evaluator/autoloader.rb
76
+ - lib/dsl_evaluator/logger.rb
46
77
  - lib/dsl_evaluator/printer.rb
47
78
  - lib/dsl_evaluator/version.rb
48
79
  homepage: https://github.com/tongueroo/dsl_evaluator
@@ -65,9 +96,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
96
  - !ruby/object:Gem::Version
66
97
  version: '0'
67
98
  requirements: []
68
- rubygems_version: 3.1.2
99
+ rubygems_version: 3.2.32
69
100
  signing_key:
70
101
  specification_version: 4
71
- summary: Small module to help with DSL evaluation. It produces a human-friendly backtrace
72
- error
102
+ summary: DSL evaluation library. It produces a human-friendly backtrace error
73
103
  test_files: []