zeitwerk 2.6.2 → 2.6.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/zeitwerk/internal.rb +12 -0
- data/lib/zeitwerk/loader/config.rb +38 -39
- data/lib/zeitwerk/loader/eager_load.rb +12 -11
- data/lib/zeitwerk/loader/helpers.rb +1 -1
- data/lib/zeitwerk/loader.rb +9 -8
- data/lib/zeitwerk/version.rb +1 -1
- data/lib/zeitwerk.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c7bbcbb7fa03b5ef6389335805145cabf2a4fdd203c15b3c6ecdf68f229e499
|
4
|
+
data.tar.gz: 3581c99a8d4431eeeed3b6139aca5363f9c13d136dddb22aa5c88b55d2ff2dac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3575d2cd414fe45f4c42ce286fbf9cbf648ed0cf5c3643db82167023adde590058cbe88c2348fe2c9f6f8d56f04858ef49441115544dca88b18b48f2eb36d886
|
7
|
+
data.tar.gz: 4d9fc1a1c72df9233e742f22ad2a0bd636301e55cd9078e856cdfb9a8b2727345d86f278e592fb0294959e9aad92895619e69133050afa943192a61477bad64d
|
data/README.md
CHANGED
@@ -536,7 +536,7 @@ The method `Zeitwerk::Loader.eager_load_namespace` broadcasts `eager_load_namesp
|
|
536
536
|
Zeitwerk::Loader.eager_load_namespace(MyFramework::Routes)
|
537
537
|
```
|
538
538
|
|
539
|
-
This may be handy, for example, if a framework supports plugins and a shared namespace needs to be eager loaded for the
|
539
|
+
This may be handy, for example, if a framework supports plugins and a shared namespace needs to be eager loaded for the framework to function properly.
|
540
540
|
|
541
541
|
Please, note that loaders only eager load namespaces they manage, as documented above. Therefore, this method does not allow you to eager load namespaces not managed by Zeitwerk loaders.
|
542
542
|
|
@@ -4,6 +4,14 @@ require "set"
|
|
4
4
|
require "securerandom"
|
5
5
|
|
6
6
|
module Zeitwerk::Loader::Config
|
7
|
+
extend Zeitwerk::Internal
|
8
|
+
|
9
|
+
# @sig #camelize
|
10
|
+
attr_accessor :inflector
|
11
|
+
|
12
|
+
# @sig #call | #debug | nil
|
13
|
+
attr_accessor :logger
|
14
|
+
|
7
15
|
# Absolute paths of the root directories. Stored in a hash to preserve order,
|
8
16
|
# easily handle duplicates, have a fast lookup needed for detecting nested
|
9
17
|
# paths, and store namespaces as values.
|
@@ -15,74 +23,70 @@ module Zeitwerk::Loader::Config
|
|
15
23
|
# This is a private collection maintained by the loader. The public
|
16
24
|
# interface for it is `push_dir` and `dirs`.
|
17
25
|
#
|
18
|
-
# @private
|
19
26
|
# @sig Hash[String, Module]
|
20
|
-
attr_reader :
|
21
|
-
|
22
|
-
# @sig #camelize
|
23
|
-
attr_accessor :inflector
|
27
|
+
attr_reader :roots
|
28
|
+
internal :roots
|
24
29
|
|
25
30
|
# Absolute paths of files, directories, or glob patterns to be totally
|
26
31
|
# ignored.
|
27
32
|
#
|
28
|
-
# @private
|
29
33
|
# @sig Set[String]
|
30
34
|
attr_reader :ignored_glob_patterns
|
35
|
+
private :ignored_glob_patterns
|
31
36
|
|
32
37
|
# The actual collection of absolute file and directory names at the time the
|
33
38
|
# ignored glob patterns were expanded. Computed on setup, and recomputed on
|
34
39
|
# reload.
|
35
40
|
#
|
36
|
-
# @private
|
37
41
|
# @sig Set[String]
|
38
42
|
attr_reader :ignored_paths
|
43
|
+
private :ignored_paths
|
39
44
|
|
40
45
|
# Absolute paths of directories or glob patterns to be collapsed.
|
41
46
|
#
|
42
|
-
# @private
|
43
47
|
# @sig Set[String]
|
44
48
|
attr_reader :collapse_glob_patterns
|
49
|
+
private :collapse_glob_patterns
|
45
50
|
|
46
51
|
# The actual collection of absolute directory names at the time the collapse
|
47
52
|
# glob patterns were expanded. Computed on setup, and recomputed on reload.
|
48
53
|
#
|
49
|
-
# @private
|
50
54
|
# @sig Set[String]
|
51
55
|
attr_reader :collapse_dirs
|
56
|
+
private :collapse_dirs
|
52
57
|
|
53
58
|
# Absolute paths of files or directories not to be eager loaded.
|
54
59
|
#
|
55
|
-
# @private
|
56
60
|
# @sig Set[String]
|
57
61
|
attr_reader :eager_load_exclusions
|
62
|
+
private :eager_load_exclusions
|
58
63
|
|
59
64
|
# User-oriented callbacks to be fired on setup and on reload.
|
60
65
|
#
|
61
|
-
# @private
|
62
66
|
# @sig Array[{ () -> void }]
|
63
67
|
attr_reader :on_setup_callbacks
|
68
|
+
private :on_setup_callbacks
|
64
69
|
|
65
70
|
# User-oriented callbacks to be fired when a constant is loaded.
|
66
71
|
#
|
67
|
-
# @private
|
68
72
|
# @sig Hash[String, Array[{ (Object, String) -> void }]]
|
69
73
|
# Hash[Symbol, Array[{ (String, Object, String) -> void }]]
|
70
74
|
attr_reader :on_load_callbacks
|
75
|
+
private :on_load_callbacks
|
71
76
|
|
72
77
|
# User-oriented callbacks to be fired before constants are removed.
|
73
78
|
#
|
74
|
-
# @private
|
75
79
|
# @sig Hash[String, Array[{ (Object, String) -> void }]]
|
76
80
|
# Hash[Symbol, Array[{ (String, Object, String) -> void }]]
|
77
81
|
attr_reader :on_unload_callbacks
|
78
|
-
|
79
|
-
# @sig #call | #debug | nil
|
80
|
-
attr_accessor :logger
|
82
|
+
private :on_unload_callbacks
|
81
83
|
|
82
84
|
def initialize
|
83
|
-
@initialized_at = Time.now
|
84
|
-
@root_dirs = {}
|
85
85
|
@inflector = Zeitwerk::Inflector.new
|
86
|
+
@logger = self.class.default_logger
|
87
|
+
@tag = SecureRandom.hex(3)
|
88
|
+
@initialized_at = Time.now
|
89
|
+
@roots = {}
|
86
90
|
@ignored_glob_patterns = Set.new
|
87
91
|
@ignored_paths = Set.new
|
88
92
|
@collapse_glob_patterns = Set.new
|
@@ -92,8 +96,6 @@ module Zeitwerk::Loader::Config
|
|
92
96
|
@on_setup_callbacks = []
|
93
97
|
@on_load_callbacks = {}
|
94
98
|
@on_unload_callbacks = {}
|
95
|
-
@logger = self.class.default_logger
|
96
|
-
@tag = SecureRandom.hex(3)
|
97
99
|
end
|
98
100
|
|
99
101
|
# Pushes `path` to the list of root directories.
|
@@ -113,7 +115,7 @@ module Zeitwerk::Loader::Config
|
|
113
115
|
abspath = File.expand_path(path)
|
114
116
|
if dir?(abspath)
|
115
117
|
raise_if_conflicting_directory(abspath)
|
116
|
-
|
118
|
+
roots[abspath] = namespace
|
117
119
|
else
|
118
120
|
raise Zeitwerk::Error, "the root directory #{abspath} does not exist"
|
119
121
|
end
|
@@ -146,9 +148,9 @@ module Zeitwerk::Loader::Config
|
|
146
148
|
# @sig () -> Array[String] | Hash[String, Module]
|
147
149
|
def dirs(namespaces: false)
|
148
150
|
if namespaces
|
149
|
-
|
151
|
+
roots.clone
|
150
152
|
else
|
151
|
-
|
153
|
+
roots.keys
|
152
154
|
end.freeze
|
153
155
|
end
|
154
156
|
|
@@ -275,71 +277,68 @@ module Zeitwerk::Loader::Config
|
|
275
277
|
# Returns true if the argument has been configured to be ignored, or is a
|
276
278
|
# descendant of an ignored directory.
|
277
279
|
#
|
278
|
-
# @private
|
279
280
|
# @sig (String) -> bool
|
280
|
-
def ignores?(abspath)
|
281
|
+
internal def ignores?(abspath)
|
281
282
|
# Common use case.
|
282
283
|
return false if ignored_paths.empty?
|
283
284
|
|
284
285
|
walk_up(abspath) do |abspath|
|
285
286
|
return true if ignored_paths.member?(abspath)
|
286
|
-
return false if
|
287
|
+
return false if roots.key?(abspath)
|
287
288
|
end
|
288
289
|
|
289
290
|
false
|
290
291
|
end
|
291
292
|
|
292
|
-
private
|
293
|
-
|
294
293
|
# @sig () -> Array[String]
|
295
|
-
def
|
296
|
-
|
294
|
+
private def actual_roots
|
295
|
+
roots.reject do |root_dir, _root_namespace|
|
297
296
|
!dir?(root_dir) || ignored_paths.member?(root_dir)
|
298
297
|
end
|
299
298
|
end
|
300
299
|
|
301
300
|
# @sig (String) -> bool
|
302
|
-
def root_dir?(dir)
|
303
|
-
|
301
|
+
private def root_dir?(dir)
|
302
|
+
roots.key?(dir)
|
304
303
|
end
|
305
304
|
|
306
305
|
# @sig (String) -> bool
|
307
|
-
def excluded_from_eager_load?(abspath)
|
306
|
+
private def excluded_from_eager_load?(abspath)
|
308
307
|
# Optimize this common use case.
|
309
308
|
return false if eager_load_exclusions.empty?
|
310
309
|
|
311
310
|
walk_up(abspath) do |abspath|
|
312
311
|
return true if eager_load_exclusions.member?(abspath)
|
313
|
-
return false if
|
312
|
+
return false if roots.key?(abspath)
|
314
313
|
end
|
315
314
|
|
316
315
|
false
|
317
316
|
end
|
318
317
|
|
319
318
|
# @sig (String) -> bool
|
320
|
-
def collapse?(dir)
|
319
|
+
private def collapse?(dir)
|
321
320
|
collapse_dirs.member?(dir)
|
322
321
|
end
|
323
322
|
|
324
323
|
# @sig (String | Pathname | Array[String | Pathname]) -> Array[String]
|
325
|
-
def expand_paths(paths)
|
324
|
+
private def expand_paths(paths)
|
326
325
|
paths.flatten.map! { |path| File.expand_path(path) }
|
327
326
|
end
|
328
327
|
|
329
328
|
# @sig (Array[String]) -> Array[String]
|
330
|
-
def expand_glob_patterns(glob_patterns)
|
329
|
+
private def expand_glob_patterns(glob_patterns)
|
331
330
|
# Note that Dir.glob works with regular file names just fine. That is,
|
332
331
|
# glob patterns technically need no wildcards.
|
333
332
|
glob_patterns.flat_map { |glob_pattern| Dir.glob(glob_pattern) }
|
334
333
|
end
|
335
334
|
|
336
335
|
# @sig () -> void
|
337
|
-
def recompute_ignored_paths
|
336
|
+
private def recompute_ignored_paths
|
338
337
|
ignored_paths.replace(expand_glob_patterns(ignored_glob_patterns))
|
339
338
|
end
|
340
339
|
|
341
340
|
# @sig () -> void
|
342
|
-
def recompute_collapse_dirs
|
341
|
+
private def recompute_collapse_dirs
|
343
342
|
collapse_dirs.replace(expand_glob_patterns(collapse_glob_patterns))
|
344
343
|
end
|
345
344
|
end
|
@@ -12,8 +12,8 @@ module Zeitwerk::Loader::EagerLoad
|
|
12
12
|
|
13
13
|
log("eager load start") if logger
|
14
14
|
|
15
|
-
|
16
|
-
actual_eager_load_dir(root_dir,
|
15
|
+
actual_roots.each do |root_dir, root_namespace|
|
16
|
+
actual_eager_load_dir(root_dir, root_namespace, force: force)
|
17
17
|
end
|
18
18
|
|
19
19
|
autoloaded_dirs.each do |autoloaded_dir|
|
@@ -40,7 +40,7 @@ module Zeitwerk::Loader::EagerLoad
|
|
40
40
|
return if ignored_paths.member?(dir)
|
41
41
|
return if eager_load_exclusions.member?(dir)
|
42
42
|
|
43
|
-
break if root_namespace =
|
43
|
+
break if root_namespace = roots[dir]
|
44
44
|
|
45
45
|
unless collapse?(dir)
|
46
46
|
basename = File.basename(dir)
|
@@ -73,23 +73,24 @@ module Zeitwerk::Loader::EagerLoad
|
|
73
73
|
|
74
74
|
return if @eager_loaded
|
75
75
|
|
76
|
-
|
76
|
+
mod_name = real_mod_name(mod)
|
77
|
+
return unless mod_name
|
78
|
+
|
79
|
+
actual_roots.each do |root_dir, root_namespace|
|
77
80
|
if mod.equal?(Object)
|
78
81
|
# A shortcircuiting test depends on the invocation of this method.
|
79
82
|
# Please keep them in sync if refactored.
|
80
83
|
actual_eager_load_dir(root_dir, root_namespace)
|
81
84
|
elsif root_namespace.equal?(Object)
|
82
|
-
eager_load_child_namespace(mod, root_dir, root_namespace)
|
85
|
+
eager_load_child_namespace(mod, mod_name, root_dir, root_namespace)
|
83
86
|
else
|
84
|
-
mod_name = real_mod_name(mod)
|
85
87
|
root_namespace_name = real_mod_name(root_namespace)
|
86
|
-
|
87
88
|
if root_namespace_name.start_with?(mod_name + "::")
|
88
89
|
actual_eager_load_dir(root_dir, root_namespace)
|
89
90
|
elsif mod_name == root_namespace_name
|
90
91
|
actual_eager_load_dir(root_dir, root_namespace)
|
91
92
|
elsif mod_name.start_with?(root_namespace_name + "::")
|
92
|
-
eager_load_child_namespace(mod, root_dir, root_namespace)
|
93
|
+
eager_load_child_namespace(mod, mod_name, root_dir, root_namespace)
|
93
94
|
else
|
94
95
|
# Unrelated constant hierarchies, do nothing.
|
95
96
|
end
|
@@ -121,7 +122,7 @@ module Zeitwerk::Loader::EagerLoad
|
|
121
122
|
walk_up(File.dirname(abspath)) do |dir|
|
122
123
|
raise Zeitwerk::Error.new("#{abspath} is ignored") if ignored_paths.member?(dir)
|
123
124
|
|
124
|
-
break if root_namespace =
|
125
|
+
break if root_namespace = roots[dir]
|
125
126
|
|
126
127
|
unless collapse?(dir)
|
127
128
|
basename = File.basename(dir)
|
@@ -180,8 +181,8 @@ module Zeitwerk::Loader::EagerLoad
|
|
180
181
|
# strict namespace descendendant of `root_namespace`.
|
181
182
|
#
|
182
183
|
# @sig (Module, String, Module, Boolean) -> void
|
183
|
-
private def eager_load_child_namespace(child, root_dir, root_namespace)
|
184
|
-
suffix =
|
184
|
+
private def eager_load_child_namespace(child, child_name, root_dir, root_namespace)
|
185
|
+
suffix = child_name
|
185
186
|
unless root_namespace.equal?(Object)
|
186
187
|
suffix = suffix.delete_prefix(real_mod_name(root_namespace) + "::")
|
187
188
|
end
|
data/lib/zeitwerk/loader.rb
CHANGED
@@ -116,8 +116,8 @@ module Zeitwerk
|
|
116
116
|
mutex.synchronize do
|
117
117
|
break if @setup
|
118
118
|
|
119
|
-
|
120
|
-
set_autoloads_in_dir(root_dir,
|
119
|
+
actual_roots.each do |root_dir, root_namespace|
|
120
|
+
set_autoloads_in_dir(root_dir, root_namespace)
|
121
121
|
end
|
122
122
|
|
123
123
|
on_setup_callbacks.each(&:call)
|
@@ -441,19 +441,20 @@ module Zeitwerk
|
|
441
441
|
# @sig (String) -> void
|
442
442
|
def raise_if_conflicting_directory(dir)
|
443
443
|
MUTEX.synchronize do
|
444
|
+
dir_slash = dir + "/"
|
445
|
+
|
444
446
|
Registry.loaders.each do |loader|
|
445
447
|
next if loader == self
|
446
|
-
next if loader.
|
448
|
+
next if loader.__ignores?(dir)
|
447
449
|
|
448
|
-
|
449
|
-
loader.root_dirs.each do |root_dir, _namespace|
|
450
|
+
loader.__roots.each_key do |root_dir|
|
450
451
|
next if ignores?(root_dir)
|
451
452
|
|
452
|
-
|
453
|
-
if
|
453
|
+
root_dir_slash = root_dir + "/"
|
454
|
+
if dir_slash.start_with?(root_dir_slash) || root_dir_slash.start_with?(dir_slash)
|
454
455
|
require "pp" # Needed for pretty_inspect, even in Ruby 2.5.
|
455
456
|
raise Error,
|
456
|
-
"loader\n\n#{pretty_inspect}\n\nwants to manage directory #{dir
|
457
|
+
"loader\n\n#{pretty_inspect}\n\nwants to manage directory #{dir}," \
|
457
458
|
" which is already managed by\n\n#{loader.pretty_inspect}\n"
|
458
459
|
EOS
|
459
460
|
end
|
data/lib/zeitwerk/version.rb
CHANGED
data/lib/zeitwerk.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zeitwerk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.6.
|
4
|
+
version: 2.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xavier Noria
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2
|
14
14
|
Zeitwerk implements constant autoloading with Ruby semantics. Each gem
|
@@ -28,6 +28,7 @@ files:
|
|
28
28
|
- lib/zeitwerk/gem_inflector.rb
|
29
29
|
- lib/zeitwerk/gem_loader.rb
|
30
30
|
- lib/zeitwerk/inflector.rb
|
31
|
+
- lib/zeitwerk/internal.rb
|
31
32
|
- lib/zeitwerk/kernel.rb
|
32
33
|
- lib/zeitwerk/loader.rb
|
33
34
|
- lib/zeitwerk/loader/callbacks.rb
|