as_deprecation_tracker 1.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b25a9c470b3310b7a3112d290e0655811ea93c3d
4
- data.tar.gz: 78857eba82e956ad61ad8e6276128fe4a73d6056
3
+ metadata.gz: 3c3db75579f6e32b233ab757406affac74f42210
4
+ data.tar.gz: 22c98db26c0c16b71993f038804b9b6e23ad7ea4
5
5
  SHA512:
6
- metadata.gz: 83efcef8a382e9c9cace6a2e942f7d96032d587b76b1ab36707cf3f7c37c82a1e6a8a241c1bdd8da5de298fe6e5ec2b2f705414f8c47208d3581059087629e0e
7
- data.tar.gz: c6558bacefd24acba76e6aa3e6bb23beff1e26cf1ec502cc010f6172f7cdd07f86affaf919509eef9b58015fb2ab7d3e761b129b16800765684a422b9aa7b94d
6
+ metadata.gz: 7d3a4345c389c3a37436cab4aaac86c981264f237e8e14d0366b9b3a85b53e24f6d567ecb3029daac26f6f438b4adf634ae1d8073a1d9edd3d175f6b727a8812
7
+ data.tar.gz: a4609be92a9373db4acba7a048f0ee320a51f027d5295a6c2c3c3cad4d608ab8ad3872cdd5eca617313337554b932d5b810fa0f76e3bbc75230a092d481582de
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2016 Dominic Cleal
1
+ Copyright (c) 2016-2017 Dominic Cleal
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -50,7 +50,10 @@ specific instances of deprecated calls which can be committed. Subsequent `rake
50
50
  test` runs will then automatically raise errors for new occurrences.
51
51
 
52
52
  Re-run tests with `AS_DEPRECATION_RECORD=yes` to append new instances to the
53
- existing configuration file, if you wish to whitelist rather than fix them.
53
+ existing whitelist file, if you wish to permit rather than fix them.
54
+
55
+ Use `AS_DEPRECATION_WHITELIST=~/rails_engine` to set a different root directory
56
+ or whitelist file to update, e.g. for a Rails engine.
54
57
 
55
58
  ### Whitelist configuration
56
59
 
@@ -71,9 +74,12 @@ array of hashes:
71
74
  callstack: "app/models/foo.rb:23:in `example_method'"
72
75
  ```
73
76
 
74
- Accepted keys are `message`, matching the exact deprecation message and
75
- `callstack`, a string or an array forming the backtrace of the deprecation.
76
- If an array is given for the callstack, all entries must match the caller.
77
+ Accepted keys are:
78
+
79
+ * `message`, matching the exact deprecation message
80
+ * `callstack`, a string or an array forming the backtrace of the deprecation.
81
+ If an array is given for the callstack, all entries must match the caller.
82
+ * `engine`, a Rails `engine_name` string, matching any call within the engine
77
83
 
78
84
  The callstack will match on as much data as is provided - if only a file is
79
85
  given, any matching deprecation within the file will be whitelisted. The line
@@ -82,6 +88,13 @@ number may vary by up to ten lines from the recorded number by default (see
82
88
  `line_tolerance` to tune). Usually the filename and method name are sufficient
83
89
  to match the caller without needing line numbers.
84
90
 
91
+ Additional whitelist files may be placed below the root of each Rails engine
92
+ and will be loaded at startup in addition to the main Rails root config file.
93
+
94
+ Entries can be added programmatically by calling
95
+ `ASDeprecationTracker.whitelist.add(message: ...)` with any of the supported
96
+ keys above supplied as keyword arguments.
97
+
85
98
  ### Configuration
86
99
 
87
100
  Use an initializer to change ASDT's behaviour at startup:
@@ -101,8 +114,8 @@ Supported options:
101
114
  to ASDeprecationTracker::Receiver at startup, may be disabled to use multiple
102
115
  behaviors (defaults to true)
103
116
  * `whitelist_file` to customise the location of the whitelist YAML file
104
- (defaults to `config/as_deprecation_whitelist.yaml` beneath the Rails root)
117
+ (defaults to `config/as_deprecation_whitelist.yaml`)
105
118
 
106
119
  ## License
107
120
 
108
- Copyright (c) 2016 Dominic Cleal. Distributed under the MIT license.
121
+ Copyright (c) 2016-2017 Dominic Cleal. Distributed under the MIT license.
@@ -9,7 +9,7 @@ module ASDeprecationTracker
9
9
  @envs = %w(test)
10
10
  @line_tolerance = 10
11
11
  @register_behavior = true
12
- @whitelist_file = File.join(Rails.root, 'config', 'as_deprecation_whitelist.yaml')
12
+ @whitelist_file = File.join('config', 'as_deprecation_whitelist.yaml')
13
13
  end
14
14
  end
15
15
  end
@@ -9,7 +9,16 @@ module ASDeprecationTracker
9
9
  ActiveSupport::Deprecation.behavior = :notify if ASDeprecationTracker.config.register_behavior?
10
10
 
11
11
  whitelist = ASDeprecationTracker.config.whitelist_file
12
- ASDeprecationTracker.whitelist.load_file(whitelist) if File.exist?(whitelist)
12
+ ([Rails.root] + engine_roots).each do |root|
13
+ engine_whitelist = File.join(root, whitelist)
14
+ ASDeprecationTracker.whitelist.load_file(engine_whitelist) if File.exist?(engine_whitelist)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def engine_roots
21
+ ::Rails::Engine.descendants.map { |engine| engine.root rescue nil }.compact.uniq # rubocop:disable Style/RescueModifier
13
22
  end
14
23
  end
15
24
  end
@@ -20,11 +20,25 @@ module ASDeprecationTracker
20
20
  private
21
21
 
22
22
  def write_deprecation(message, callstack)
23
- writer = ASDeprecationTracker::Writer.new(ASDeprecationTracker.config.whitelist_file)
23
+ writer = ASDeprecationTracker::Writer.new(whitelist_file)
24
24
  writer.add(message, callstack)
25
25
  writer.write_file
26
26
  end
27
27
 
28
+ def whitelist_file
29
+ root = if ENV['AS_DEPRECATION_WHITELIST'].present?
30
+ File.expand_path(ENV['AS_DEPRECATION_WHITELIST'])
31
+ else
32
+ Rails.root
33
+ end
34
+
35
+ if File.directory?(root)
36
+ File.join(root, ASDeprecationTracker.config.whitelist_file)
37
+ else
38
+ root
39
+ end
40
+ end
41
+
28
42
  def raise_deprecation(message, callstack)
29
43
  e = ActiveSupport::DeprecationException.new(message)
30
44
  e.set_backtrace(callstack)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ASDeprecationTracker
3
- VERSION = '1.0.0'.freeze
3
+ VERSION = '1.1.0'.freeze
4
4
  end
@@ -11,9 +11,10 @@ module ASDeprecationTracker
11
11
  @list = []
12
12
  end
13
13
 
14
- def add_to_list(entries)
15
- entries.each { |entry| @list << WhitelistEntry.new(entry) }
14
+ def add_to_list(*entries)
15
+ entries.flatten.each { |entry| @list << WhitelistEntry.new(entry.symbolize_keys) }
16
16
  end
17
+ alias_method :add, :add_to_list
17
18
 
18
19
  def clear
19
20
  @list.clear
@@ -3,21 +3,24 @@ module ASDeprecationTracker
3
3
  # Configuration of a whitelisted (known) deprecation warning matched by data
4
4
  # such as a message and/or callstack
5
5
  class WhitelistEntry
6
+ KNOWN_KEYS = %w(callstack engine message).freeze
6
7
  MESSAGE_CLEANUP_RE = Regexp.new('\ADEPRECATION WARNING: (.+) \(called from.*')
7
8
  CALLSTACK_FILE_RE = Regexp.new('\A(.*?)(?::(\d+))?(?::in `(.+)\')?\z')
8
9
 
9
- def initialize(entry)
10
- entry = entry.with_indifferent_access
11
- raise('Missing `message` or `callstack` from whitelist entry') unless entry.key?(:message) || entry.key?(:callstack)
12
- @message = entry[:message]
13
- @callstack = callstack_to_files_lines(Array.wrap(entry[:callstack]))
10
+ def initialize(callstack: [], engine: nil, message: nil)
11
+ @callstack = callstack_to_files_lines(Array.wrap(callstack))
12
+ @engine_root = engine.present? ? engine_root(engine) : nil
13
+ @message = message
14
14
  end
15
15
 
16
+ # rubocop:disable Metrics/CyclomaticComplexity
16
17
  def matches?(deprecation)
17
18
  return false if @message.present? && !message_matches?(deprecation[:message])
18
19
  return false if @callstack.present? && !callstack_matches?(deprecation[:callstack])
20
+ return false if @engine_root.present? && !engine_root_matches?(deprecation[:callstack])
19
21
  true
20
22
  end
23
+ # rubocop:enable Metrics/CyclomaticComplexity
21
24
 
22
25
  private
23
26
 
@@ -35,6 +38,7 @@ module ASDeprecationTracker
35
38
  end
36
39
 
37
40
  def callstack_matches?(callstack)
41
+ callstack = Rails::BacktraceCleaner.new.clean(callstack, :silent)
38
42
  callstack = callstack_to_files_lines(callstack)
39
43
 
40
44
  @callstack.all? do |whitelist_entry|
@@ -59,5 +63,20 @@ module ASDeprecationTracker
59
63
  return true if method1.nil? || method2.nil?
60
64
  method1 == method2
61
65
  end
66
+
67
+ def engine_root_matches?(callstack)
68
+ callstack.any? { |callstack_entry| callstack_entry.start_with?(@engine_root) }
69
+ end
70
+
71
+ def engine_root(engine_name)
72
+ ::Rails::Engine.descendants.each do |engine|
73
+ begin
74
+ return engine.root.to_s if engine_name == engine.engine_name
75
+ rescue NoMethodError, RuntimeError # rubocop:disable Lint/HandleExceptions
76
+ # Ignore failures with singleton engine subclasses etc.
77
+ end
78
+ end
79
+ raise("Unknown configured engine name #{engine_name}")
80
+ end
62
81
  end
63
82
  end
@@ -36,7 +36,7 @@ class ConfigurationTest < ASDeprecationTracker::TestCase
36
36
 
37
37
  def test_whitelist_file
38
38
  assert_kind_of String, @config.whitelist_file
39
- assert File.exist?(@config.whitelist_file)
39
+ assert File.exist?(File.join(Rails.root, @config.whitelist_file))
40
40
  end
41
41
 
42
42
  def test_whitelist_file=
@@ -40,6 +40,31 @@ class ReceiverTest < ASDeprecationTracker::TestCase
40
40
  ActiveSupport::Notifications.instrument('deprecation.rails', message: 'test')
41
41
  end
42
42
 
43
+ def test_whitelist_file_root
44
+ assert_equal File.join(Rails.root, 'config', 'as_deprecation_whitelist.yaml'), ASDeprecationTracker::Receiver.new.send(:whitelist_file)
45
+ end
46
+
47
+ def test_whitelist_file_env_directory
48
+ ENV['AS_DEPRECATION_WHITELIST'] = '/'
49
+ assert_equal File.join('/', 'config', 'as_deprecation_whitelist.yaml'), ASDeprecationTracker::Receiver.new.send(:whitelist_file)
50
+ ensure
51
+ ENV.delete('AS_DEPRECATION_WHITELIST')
52
+ end
53
+
54
+ def test_whitelist_file_env_file
55
+ ENV['AS_DEPRECATION_WHITELIST'] = '/as_deprecation_whitelist.yaml'
56
+ assert_equal '/as_deprecation_whitelist.yaml', ASDeprecationTracker::Receiver.new.send(:whitelist_file)
57
+ ensure
58
+ ENV.delete('AS_DEPRECATION_WHITELIST')
59
+ end
60
+
61
+ def test_whitelist_file_env_expand
62
+ ENV['AS_DEPRECATION_WHITELIST'] = File.join(Rails.root, '..', 'as_deprecation_whitelist.yaml')
63
+ assert_equal File.expand_path('../as_deprecation_whitelist.yaml', Rails.root), ASDeprecationTracker::Receiver.new.send(:whitelist_file)
64
+ ensure
65
+ ENV.delete('AS_DEPRECATION_WHITELIST')
66
+ end
67
+
43
68
  private
44
69
 
45
70
  def event(payload)
@@ -2,11 +2,7 @@
2
2
  require 'test_helper'
3
3
 
4
4
  class WhitelistEntryTest < ASDeprecationTracker::TestCase
5
- def test_initialize_with_strings
6
- ASDeprecationTracker::WhitelistEntry.new('message' => 'test')
7
- end
8
-
9
- def test_initialize_with_symbols
5
+ def test_initialize
10
6
  ASDeprecationTracker::WhitelistEntry.new(message: 'test')
11
7
  end
12
8
 
@@ -27,54 +23,54 @@ class WhitelistEntryTest < ASDeprecationTracker::TestCase
27
23
  end
28
24
 
29
25
  def test_matches_partial_callstack_top
30
- assert entry(callstack: ['/home/user/app/models/foo.rb:23']).matches?(deprecation)
26
+ assert entry(callstack: ['app/models/foo.rb:23']).matches?(deprecation)
31
27
  end
32
28
 
33
29
  def test_matches_partial_callstack_bottom
34
- assert entry(callstack: ['/home/user/app/controllers/foos_controller.rb:42']).matches?(deprecation)
30
+ assert entry(callstack: ['app/controllers/foos_controller.rb:42']).matches?(deprecation)
35
31
  end
36
32
 
37
33
  def test_matches_partial_callstack_multiple
38
34
  assert entry(callstack: [
39
- '/home/user/app/models/foo.rb:23',
40
- '/home/user/app/controllers/foos_controller.rb:42'
35
+ 'app/models/foo.rb:23',
36
+ 'app/controllers/foos_controller.rb:42'
41
37
  ]).matches?(deprecation)
42
38
  end
43
39
 
44
40
  def test_matches_partial_callstack_within_tolerance
45
- assert entry(callstack: ['/home/user/app/models/foo.rb:25']).matches?(deprecation)
41
+ assert entry(callstack: ['app/models/foo.rb:25']).matches?(deprecation)
46
42
  end
47
43
 
48
44
  def test_matches_partial_callstack_outside_tolerance
49
- refute entry(callstack: ['/home/user/app/models/foo.rb:34']).matches?(deprecation)
45
+ refute entry(callstack: ['app/models/foo.rb:34']).matches?(deprecation)
50
46
  end
51
47
 
52
48
  def test_matches_partial_callstack_same_method
53
- assert entry(callstack: ['/home/user/app/models/foo.rb:in `example_method\'']).matches?(deprecation)
49
+ assert entry(callstack: ['app/models/foo.rb:in `example_method\'']).matches?(deprecation)
54
50
  end
55
51
 
56
52
  def test_matches_partial_callstack_different_method
57
- refute entry(callstack: ['/home/user/app/models/foo.rb:23:in `another_method\'']).matches?(deprecation)
53
+ refute entry(callstack: ['app/models/foo.rb:23:in `another_method\'']).matches?(deprecation)
58
54
  end
59
55
 
60
56
  def test_matches_partial_callstack_different_method_no_line
61
- refute entry(callstack: ['/home/user/app/models/foo.rb:in `another_method\'']).matches?(deprecation)
57
+ refute entry(callstack: ['app/models/foo.rb:in `another_method\'']).matches?(deprecation)
62
58
  end
63
59
 
64
60
  def test_matches_partial_callstack_within_tolerance_same_method
65
- assert entry(callstack: ['/home/user/app/models/foo.rb:25:in `example_method\'']).matches?(deprecation)
61
+ assert entry(callstack: ['app/models/foo.rb:25:in `example_method\'']).matches?(deprecation)
66
62
  end
67
63
 
68
64
  def test_matches_partial_callstack_outside_tolerance_same_method
69
- refute entry(callstack: ['/home/user/app/models/foo.rb:34:in `example_method\'']).matches?(deprecation)
65
+ refute entry(callstack: ['app/models/foo.rb:34:in `example_method\'']).matches?(deprecation)
70
66
  end
71
67
 
72
68
  def test_matches_partial_callstack_string
73
- assert entry(callstack: '/home/user/app/models/foo.rb:23').matches?(deprecation)
69
+ assert entry(callstack: 'app/models/foo.rb:23').matches?(deprecation)
74
70
  end
75
71
 
76
72
  def test_matches_partial_callstack_file
77
- assert entry(callstack: ['/home/user/app/models/foo.rb']).matches?(deprecation)
73
+ assert entry(callstack: ['app/models/foo.rb']).matches?(deprecation)
78
74
  end
79
75
 
80
76
  def test_matches_different_message_same_callstack
@@ -89,20 +85,44 @@ class WhitelistEntryTest < ASDeprecationTracker::TestCase
89
85
  refute entry.matches?(deprecation(message: 'a different method is deprecated', callstack: caller))
90
86
  end
91
87
 
88
+ def test_matches_only_engine
89
+ assert entry(engine: 'example').matches?(deprecation(called_in_engine: 'example'))
90
+ end
91
+
92
+ def test_matches_different_engine
93
+ refute entry(engine: 'another').matches?(deprecation(called_in_engine: 'example'))
94
+ end
95
+
96
+ def test_matches_outside_engine
97
+ refute entry(engine: 'another').matches?(deprecation(called_in_engine: 'example'))
98
+ end
99
+
92
100
  private
93
101
 
94
- def deprecation(overrides = {})
102
+ def default_deprecation
95
103
  {
96
104
  message: 'uniq is deprecated and will be removed',
97
105
  callstack: [
98
- '/home/user/app/models/foo.rb:23:in `example_method\'',
99
- '/home/user/app/controllers/foos_controller.rb:42:in `update\'',
100
- '/home/user/test/controllers/foos_controller_test.rb:18:in `block in <class:FoosControllerTest>\''
106
+ "#{Rails.root}/app/models/foo.rb:23:in `example_method'",
107
+ "#{Rails.root}/app/controllers/foos_controller.rb:42:in `update'",
108
+ "#{Rails.root}/test/controllers/foos_controller_test.rb:18:in `block in <class:FoosControllerTest>'"
101
109
  ]
102
- }.merge(overrides).compact
110
+ }
111
+ end
112
+
113
+ def deprecation(overrides = {})
114
+ deprecation = default_deprecation
115
+ if (engine = overrides.delete(:called_in_engine))
116
+ deprecation[:callstack] << "/home/user/engines/#{engine}/app/middleware/foo.rb:12:in `call'"
117
+ end
118
+ deprecation.merge(overrides).compact
103
119
  end
104
120
 
105
121
  def entry(overrides = {})
106
- ASDeprecationTracker::WhitelistEntry.new(deprecation(overrides))
122
+ entry_hash = default_deprecation.merge(overrides).compact
123
+ entry_hash[:callstack].map! { |line| line.sub(Rails.root.to_s + '/', '') } if entry_hash[:callstack].is_a?(Array)
124
+
125
+ ASDeprecationTracker::WhitelistEntry.any_instance.expects(:engine_root).with(overrides[:engine]).returns("/home/user/engines/#{overrides[:engine]}") if overrides.key?(:engine)
126
+ ASDeprecationTracker::WhitelistEntry.new(entry_hash)
107
127
  end
108
128
  end
@@ -7,11 +7,21 @@ class WhitelistTest < ASDeprecationTracker::TestCase
7
7
  super
8
8
  end
9
9
 
10
+ def test_add
11
+ @whitelist.add(entry)
12
+ assert_equal 1, @whitelist.list.count
13
+ end
14
+
10
15
  def test_add_to_list
11
16
  @whitelist.add_to_list([entry])
12
17
  assert_equal 1, @whitelist.list.count
13
18
  end
14
19
 
20
+ def test_add_to_list_string_keys
21
+ @whitelist.add_to_list([entry.stringify_keys])
22
+ assert_equal 1, @whitelist.list.count
23
+ end
24
+
15
25
  def test_clear
16
26
  @whitelist.add_to_list([entry])
17
27
  @whitelist.clear
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: as_deprecation_tracker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominic Cleal
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-02 00:00:00.000000000 Z
11
+ date: 2017-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport