nanoc 4.8.16 → 4.8.17

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: cfa738915a0c601d828aa97183ebbfee9613ee9e2b955ad0f52e6a3dbea6545e
4
- data.tar.gz: 6f0989008933306c049073a1b384c9715969116dafb8fc0279390b1b4ec003dd
3
+ metadata.gz: 2b0135cd287173e9725acef9bb921109f8158d9e6453bd8e7ae194e23cdd25ef
4
+ data.tar.gz: 115b6b3baf84924b26cacac37925023f0aacbb9530721bd093386a74102fbd10
5
5
  SHA512:
6
- metadata.gz: 8d7af61ff23c5a1f80e2d1b4e80bdb22f684ddca32391e9f19bb3fc44630a675d4cb29f7fbe9e1764f899e691dff0fad7d252e59e34bca86544edf397a07e0a5
7
- data.tar.gz: 58286c12cf1b0037db772e116c456f4d851d53c64d7ede2a151b9c30611f71b4a9e35cd5b5f7f3609b2b1323b2aa2eec82540393b5d4b6ba9c47f97fb709b81e
6
+ metadata.gz: c8aa8b0d5005dfbaa7664d08baaeee74bc7e5fb15cd2873d18bb0d4847c4c76203539852a258c4ad7c5187cb6503db1396e0a43752926f51fe89ea66b04dce12
7
+ data.tar.gz: 19fd6556430be0ffda0d733f0e8546a0ac646e7deb8da0e62df17c9caae4e99c166f4cc6bf8aadfc39376d5a1df44f53c542f104fefbf404686b840b4d18ced0
data/NEWS.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Nanoc news
2
2
 
3
+ ## 4.8.17 (2017-12-16)
4
+
5
+ Enhancements:
6
+
7
+ * Made `LoadError` be printed more nicely (#1273, #1274, #1275)
8
+
3
9
  ## 4.8.16 (2017-12-09)
4
10
 
5
11
  Fixes:
@@ -1,5 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Load external dependencies
4
+ require 'addressable'
5
+ require 'ddplugin'
6
+ require 'hamster'
7
+ require 'ref'
8
+ require 'slow_enumerator_tools'
9
+ require 'ddmemoize'
10
+ require 'ddtelemetry'
11
+
3
12
  module Nanoc
4
13
  # @return [String] A string containing information about this Nanoc version
5
14
  # and its environment (Ruby engine and version, Rubygems version if any).
@@ -16,15 +25,9 @@ module Nanoc
16
25
  def self.on_windows?
17
26
  RUBY_PLATFORM =~ /windows|bccwin|cygwin|djgpp|mingw|mswin|wince/i
18
27
  end
19
- end
20
28
 
21
- # Load external dependencies
22
- require 'addressable'
23
- require 'ddplugin'
24
- require 'hamster'
25
- require 'ref'
26
- require 'slow_enumerator_tools'
27
- require 'ddtelemetry'
29
+ MEMOIZATION_TELEMETRY = DDTelemetry.new
30
+ end
28
31
 
29
32
  # Load general requirements
30
33
  require 'cgi'
@@ -6,7 +6,6 @@ end
6
6
 
7
7
  require_relative 'base/core_ext'
8
8
  require_relative 'base/contracts_support'
9
- require_relative 'base/memoization'
10
9
  require_relative 'base/error'
11
10
  require_relative 'base/errors'
12
11
  require_relative 'base/changes_stream'
@@ -4,7 +4,7 @@ module Nanoc::Int
4
4
  class ActionSequence
5
5
  include Nanoc::Int::ContractsSupport
6
6
  include Enumerable
7
- extend Nanoc::Int::Memoization
7
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
8
8
 
9
9
  attr_reader :item_rep
10
10
  attr_reader :actions
@@ -3,7 +3,6 @@
3
3
  module Nanoc::Int
4
4
  class ChecksumCollection
5
5
  include Nanoc::Int::ContractsSupport
6
- extend Nanoc::Int::Memoization
7
6
 
8
7
  c_obj = C::Or[Nanoc::Int::Item, Nanoc::Int::Layout, Nanoc::Int::Configuration, Nanoc::Int::CodeSnippet]
9
8
 
@@ -3,10 +3,11 @@
3
3
  module Nanoc::Int
4
4
  # @api private
5
5
  class IdentifiableCollection
6
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
7
+
6
8
  include Nanoc::Int::ContractsSupport
7
9
  include Enumerable
8
10
 
9
- extend Nanoc::Int::Memoization
10
11
  extend Forwardable
11
12
 
12
13
  def_delegator :@objects, :each
@@ -6,7 +6,7 @@ module Nanoc::Int
6
6
  # @api private
7
7
  class OutdatednessChecker
8
8
  class Basic
9
- extend Nanoc::Int::Memoization
9
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
10
10
 
11
11
  include Nanoc::Int::ContractsSupport
12
12
 
@@ -97,7 +97,7 @@ module Nanoc::Int
97
97
  end
98
98
  end
99
99
 
100
- extend Nanoc::Int::Memoization
100
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
101
101
 
102
102
  include Nanoc::Int::ContractsSupport
103
103
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Nanoc::Int::OutdatednessRules
4
4
  class CodeSnippetsModified < Nanoc::Int::OutdatednessRule
5
- extend Nanoc::Int::Memoization
5
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
6
6
 
7
7
  include Nanoc::Int::ContractsSupport
8
8
 
@@ -100,14 +100,6 @@ module Nanoc::CLI::Commands::CompileListeners
100
100
 
101
101
  @telemetry.summary(:phases).observe(stopwatch.duration, phase_name)
102
102
  end
103
-
104
- on(:memoization_miss) do |label|
105
- @telemetry.counter(:memoization).increment([label, :miss])
106
- end
107
-
108
- on(:memoization_hit) do |label|
109
- @telemetry.counter(:memoization).increment([label, :hit])
110
- end
111
103
  end
112
104
 
113
105
  # @see Listener#stop
@@ -146,32 +138,12 @@ module Nanoc::CLI::Commands::CompileListeners
146
138
  [headers] + rows
147
139
  end
148
140
 
149
- def table_for_memoization
150
- headers = %w[memoization hit miss %]
151
-
152
- rows_raw = @telemetry.counter(:memoization).map do |(name, type), counter|
153
- { name: name, type: type, count: counter.value }
154
- end
155
-
156
- rows = rows_raw.group_by { |r| r[:name] }.map do |name, rows_for_name|
157
- rows_by_type = rows_for_name.group_by { |r| r[:type] }
158
-
159
- num_hit = rows_by_type.fetch(:hit, []).fetch(0, {}).fetch(:count, 0)
160
- num_miss = rows_by_type.fetch(:miss, []).fetch(0, {}).fetch(:count, 0)
161
- pct = num_hit.to_f / (num_hit + num_miss).to_f
162
-
163
- [name, num_hit.to_s, num_miss.to_s, "#{format('%3.1f', pct * 100)}%"]
164
- end
165
-
166
- [headers] + rows
167
- end
168
-
169
141
  def print_profiling_feedback
170
142
  print_table_for_summary(:filters)
171
143
  print_table_for_summary(:phases) if Nanoc::CLI.verbosity >= 2
172
144
  print_table_for_summary_duration(:stages) if Nanoc::CLI.verbosity >= 2
173
145
  print_table_for_summary(:outdatedness_rules) if Nanoc::CLI.verbosity >= 2
174
- print_table_for_memoization if Nanoc::CLI.verbosity >= 2
146
+ DDMemoize.print_telemetry(Nanoc::MEMOIZATION_TELEMETRY) if Nanoc::CLI.verbosity >= 2
175
147
  end
176
148
 
177
149
  def print_table_for_summary(name)
@@ -188,13 +160,6 @@ module Nanoc::CLI::Commands::CompileListeners
188
160
  print_table(table_for_summary_durations(name))
189
161
  end
190
162
 
191
- def print_table_for_memoization
192
- return if @telemetry.counter(:memoization).empty?
193
-
194
- puts
195
- print_table(table_for_memoization)
196
- end
197
-
198
163
  def print_table(rows)
199
164
  puts DDTelemetry::Table.new(rows).to_s
200
165
  end
@@ -58,12 +58,20 @@ module Nanoc::CLI
58
58
  rescue Interrupt
59
59
  exit(1)
60
60
  rescue StandardError, ScriptError => e
61
- if trivial?(e)
62
- $stderr.puts "Error: #{e.message}"
63
- resolution = resolution_for(e)
64
- $stderr.puts resolution if resolution
61
+ handle_error(e, exit_on_error: exit_on_error)
62
+ end
63
+
64
+ def handle_error(error, exit_on_error:)
65
+ if trivial?(error)
66
+ $stderr.puts
67
+ $stderr.puts "Error: #{error.message}"
68
+ resolution = resolution_for(error)
69
+ if resolution
70
+ $stderr.puts
71
+ $stderr.puts resolution
72
+ end
65
73
  else
66
- print_error(e)
74
+ print_error(error)
67
75
  end
68
76
  exit(1) if exit_on_error
69
77
  end
@@ -148,6 +156,18 @@ module Nanoc::CLI
148
156
  feature_enabled || ruby_2_5_used
149
157
  end
150
158
 
159
+ # @api private
160
+ def trivial?(error)
161
+ case error
162
+ when Nanoc::Int::Errors::GenericTrivial, Errno::EADDRINUSE
163
+ true
164
+ when LoadError
165
+ GEM_NAMES.keys.include?(gem_name_from_load_error(error))
166
+ else
167
+ false
168
+ end
169
+ end
170
+
151
171
  protected
152
172
 
153
173
  # @return [Hash<String, Array>] A hash containing the gem names as keys and gem versions as value
@@ -196,15 +216,6 @@ module Nanoc::CLI
196
216
  'w3c_validators' => 'w3c_validators',
197
217
  }.freeze
198
218
 
199
- def trivial?(error)
200
- case error
201
- when Nanoc::Int::Errors::GenericTrivial, Errno::EADDRINUSE
202
- true
203
- else
204
- false
205
- end
206
- end
207
-
208
219
  # Attempts to find a resolution for the given error, or nil if no
209
220
  # resolution can be automatically obtained.
210
221
  #
@@ -216,15 +227,15 @@ module Nanoc::CLI
216
227
 
217
228
  case error
218
229
  when LoadError
219
- # Get gem name
220
- matches = error.message.match(/(no such file to load|cannot load such file) -- ([^\s]+)/)
221
- return nil if matches.nil?
222
- gem_name = GEM_NAMES[matches[2]]
230
+ gem_name = gem_name_from_load_error(error)
223
231
 
224
- # Build message
225
232
  if gem_name
226
233
  if using_bundler?
227
- 'Make sure the gem is added to Gemfile and run `bundle install`.'
234
+ <<~RES
235
+ 1. Add `gem '#{gem_name}'` to your Gemfile
236
+ 2. Run `bundle install`
237
+ 3. Re-run this command
238
+ RES
228
239
  else
229
240
  "Install the '#{gem_name}' gem using `gem install #{gem_name}`."
230
241
  end
@@ -241,6 +252,12 @@ module Nanoc::CLI
241
252
  end
242
253
  end
243
254
 
255
+ def gem_name_from_load_error(error)
256
+ matches = error.message.match(/(no such file to load|cannot load such file) -- ([^\s]+)/)
257
+ return nil if matches.nil?
258
+ GEM_NAMES[matches[2]]
259
+ end
260
+
244
261
  def using_bundler?
245
262
  defined?(Bundler) && Bundler::SharedHelpers.in_bundle?
246
263
  end
@@ -6,7 +6,7 @@ module Nanoc::RuleDSL
6
6
  #
7
7
  # @api private
8
8
  class ActionSequenceCalculator
9
- extend Nanoc::Int::Memoization
9
+ DDMemoize.activate(self, telemetry: Nanoc::MEMOIZATION_TELEMETRY)
10
10
 
11
11
  class UnsupportedObjectTypeException < ::Nanoc::Error
12
12
  def initialize(obj)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Nanoc
4
4
  # The current Nanoc version.
5
- VERSION = '4.8.16'
5
+ VERSION = '4.8.17'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.16
4
+ version: 4.8.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Defreyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-09 00:00:00.000000000 Z
11
+ date: 2017-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ddmemoize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.0a2
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0a2
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: ddplugin
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -162,7 +176,6 @@ files:
162
176
  - lib/nanoc/base/error.rb
163
177
  - lib/nanoc/base/errors.rb
164
178
  - lib/nanoc/base/feature.rb
165
- - lib/nanoc/base/memoization.rb
166
179
  - lib/nanoc/base/repos.rb
167
180
  - lib/nanoc/base/repos/action_sequence_store.rb
168
181
  - lib/nanoc/base/repos/aggregate_data_source.rb
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Int
4
- # Adds support for memoizing functions.
5
- #
6
- # @api private
7
- module Memoization
8
- class Value
9
- attr_reader :value
10
-
11
- def initialize(value)
12
- @value = value
13
- end
14
- end
15
-
16
- NONE = Object.new
17
-
18
- # Memoizes the method with the given name. The modified method will cache
19
- # the results of the original method, so that calling a method twice with
20
- # the same arguments will short-circuit and return the cached results
21
- # immediately.
22
- #
23
- # Memoization assumes that the current object as well as the function
24
- # arguments are immutable. Mutating the object or the arguments will not
25
- # cause memoized methods to recalculate their results. There is no way to
26
- # un-memoize a result, and calculation results will remain in memory even
27
- # if they are no longer needed.
28
- #
29
- # @example A fast fib function due to memoization
30
- #
31
- # class FibFast
32
- #
33
- # extend Nanoc::Int::Memoization
34
- #
35
- # def run(n)
36
- # if n == 0
37
- # 0
38
- # elsif n == 1
39
- # 1
40
- # else
41
- # run(n-1) + run(n-2)
42
- # end
43
- # end
44
- # memoize :run
45
- #
46
- # end
47
- #
48
- # @param [Symbol, String] method_name The name of the method to memoize
49
- #
50
- # @return [void]
51
- def memoize(method_name)
52
- original_method_name = '__nonmemoized_' + method_name.to_s
53
- alias_method original_method_name, method_name
54
-
55
- instance_cache = Hash.new { |hash, key| hash[key] = {} }
56
-
57
- define_method(method_name) do |*args|
58
- instance_method_cache = instance_cache[self]
59
-
60
- value = NONE
61
- if instance_method_cache.key?(args)
62
- object = instance_method_cache[args].object
63
- value = object ? object.value : NONE
64
- end
65
-
66
- counter_label = is_a?(Class) ? "#{self}.#{method_name}" : "#{self.class}##{method_name}"
67
- if value.equal?(NONE)
68
- Nanoc::Int::NotificationCenter.post(:memoization_miss, counter_label)
69
- send(original_method_name, *args).tap do |r|
70
- instance_method_cache[args] = Ref::SoftReference.new(Value.new(r))
71
- end
72
- else
73
- Nanoc::Int::NotificationCenter.post(:memoization_hit, counter_label)
74
- value
75
- end
76
- end
77
- end
78
- alias memoized memoize
79
- end
80
- end