zeitwerk 2.6.9 → 2.6.11
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 +4 -4
- data/README.md +1 -1
- data/lib/zeitwerk/loader/callbacks.rb +4 -3
- data/lib/zeitwerk/loader/helpers.rb +44 -0
- data/lib/zeitwerk/loader.rb +19 -51
- data/lib/zeitwerk/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0dd43924a88fceee915258e119a02df8fb173199576f52cf18c8298aab091361
|
|
4
|
+
data.tar.gz: 6aeeced1ce99e28238ebd1488a543da6ba4fb885e283f999cec30a49db3a0ccf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ca6b895667327b79fe51d504de760150aeceba5edb64400a6976962c1241bb8061f5c29e4d8584ba888694a0b1b30cf2f149f66f52181089fda262dde541d902
|
|
7
|
+
data.tar.gz: 8393b41bda4187ce0195ce5b1192455a2bc574291188b0eba86f31af88fc66e3d441717823ac07407f8c7be4e4a97de06cb5bc1922a133e66ed51cc91f6eb1c7
|
data/README.md
CHANGED
|
@@ -1296,7 +1296,7 @@ If the argument corresponds to an [ignored file or directory](#ignoring-parts-of
|
|
|
1296
1296
|
loader.cpath_expected_at("non_existing_file.rb") # => Zeitwerk::Error
|
|
1297
1297
|
```
|
|
1298
1298
|
|
|
1299
|
-
`
|
|
1299
|
+
`Zeitwerk::NameError` is raised if a constant path cannot be derived from it:
|
|
1300
1300
|
|
|
1301
1301
|
```ruby
|
|
1302
1302
|
loader.cpath_expected_at("8.rb") # => Zeitwerk::NameError
|
|
@@ -32,8 +32,9 @@ module Zeitwerk::Loader::Callbacks
|
|
|
32
32
|
# @private
|
|
33
33
|
# @sig (String) -> void
|
|
34
34
|
def on_dir_autoloaded(dir)
|
|
35
|
-
# Module#autoload does not serialize concurrent requires, and
|
|
36
|
-
# directories ourselves
|
|
35
|
+
# Module#autoload does not serialize concurrent requires in CRuby < 3.2, and
|
|
36
|
+
# we handle directories ourselves without going through Kernel#require, so
|
|
37
|
+
# the callback needs to account for concurrency.
|
|
37
38
|
#
|
|
38
39
|
# Multi-threading would introduce a race condition here in which thread t1
|
|
39
40
|
# autovivifies the module, and while autoloads for its children are being
|
|
@@ -43,7 +44,7 @@ module Zeitwerk::Loader::Callbacks
|
|
|
43
44
|
# That not only would reassign the constant (undesirable per se) but, worse,
|
|
44
45
|
# the module object created by t2 wouldn't have any of the autoloads for its
|
|
45
46
|
# children, since t1 would have correctly deleted its namespace_dirs entry.
|
|
46
|
-
|
|
47
|
+
dirs_autoload_monitor.synchronize do
|
|
47
48
|
if cref = autoloads.delete(dir)
|
|
48
49
|
autovivified_module = cref[0].const_set(cref[1], Module.new)
|
|
49
50
|
cpath = autovivified_module.name
|
|
@@ -140,4 +140,48 @@ module Zeitwerk::Loader::Helpers
|
|
|
140
140
|
private def crem(parent, cname)
|
|
141
141
|
parent.__send__(:remove_const, cname)
|
|
142
142
|
end
|
|
143
|
+
|
|
144
|
+
CNAME_VALIDATOR = Module.new
|
|
145
|
+
private_constant :CNAME_VALIDATOR
|
|
146
|
+
|
|
147
|
+
# @raise [Zeitwerk::NameError]
|
|
148
|
+
# @sig (String, String) -> Symbol
|
|
149
|
+
private def cname_for(basename, abspath)
|
|
150
|
+
cname = inflector.camelize(basename, abspath)
|
|
151
|
+
|
|
152
|
+
unless cname.is_a?(String)
|
|
153
|
+
raise TypeError, "#{inflector.class}#camelize must return a String, received #{cname.inspect}"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
if cname.include?("::")
|
|
157
|
+
raise Zeitwerk::NameError.new(<<~MESSAGE, cname)
|
|
158
|
+
wrong constant name #{cname} inferred by #{inflector.class} from
|
|
159
|
+
|
|
160
|
+
#{abspath}
|
|
161
|
+
|
|
162
|
+
#{inflector.class}#camelize should return a simple constant name without "::"
|
|
163
|
+
MESSAGE
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
begin
|
|
167
|
+
CNAME_VALIDATOR.const_defined?(cname, false)
|
|
168
|
+
rescue ::NameError => error
|
|
169
|
+
path_type = ruby?(abspath) ? "file" : "directory"
|
|
170
|
+
|
|
171
|
+
raise Zeitwerk::NameError.new(<<~MESSAGE, error.name)
|
|
172
|
+
#{error.message} inferred by #{inflector.class} from #{path_type}
|
|
173
|
+
|
|
174
|
+
#{abspath}
|
|
175
|
+
|
|
176
|
+
Possible ways to address this:
|
|
177
|
+
|
|
178
|
+
* Tell Zeitwerk to ignore this particular #{path_type}.
|
|
179
|
+
* Tell Zeitwerk to ignore one of its parent directories.
|
|
180
|
+
* Rename the #{path_type} to comply with the naming conventions.
|
|
181
|
+
* Modify the inflector to handle this case.
|
|
182
|
+
MESSAGE
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
cname.to_sym
|
|
186
|
+
end
|
|
143
187
|
end
|
data/lib/zeitwerk/loader.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "monitor"
|
|
3
4
|
require "set"
|
|
4
5
|
|
|
5
6
|
module Zeitwerk
|
|
@@ -91,9 +92,9 @@ module Zeitwerk
|
|
|
91
92
|
attr_reader :mutex
|
|
92
93
|
private :mutex
|
|
93
94
|
|
|
94
|
-
# @sig
|
|
95
|
-
attr_reader :
|
|
96
|
-
private :
|
|
95
|
+
# @sig Monitor
|
|
96
|
+
attr_reader :dirs_autoload_monitor
|
|
97
|
+
private :dirs_autoload_monitor
|
|
97
98
|
|
|
98
99
|
def initialize
|
|
99
100
|
super
|
|
@@ -103,11 +104,12 @@ module Zeitwerk
|
|
|
103
104
|
@to_unload = {}
|
|
104
105
|
@namespace_dirs = Hash.new { |h, cpath| h[cpath] = [] }
|
|
105
106
|
@shadowed_files = Set.new
|
|
106
|
-
@mutex = Mutex.new
|
|
107
|
-
@mutex2 = Mutex.new
|
|
108
107
|
@setup = false
|
|
109
108
|
@eager_loaded = false
|
|
110
109
|
|
|
110
|
+
@mutex = Mutex.new
|
|
111
|
+
@dirs_autoload_monitor = Monitor.new
|
|
112
|
+
|
|
111
113
|
Registry.register_loader(self)
|
|
112
114
|
end
|
|
113
115
|
|
|
@@ -237,15 +239,13 @@ module Zeitwerk
|
|
|
237
239
|
return unless dir?(abspath) || ruby?(abspath)
|
|
238
240
|
return if ignored_path?(abspath)
|
|
239
241
|
|
|
240
|
-
|
|
241
|
-
abspaths = []
|
|
242
|
+
paths = []
|
|
242
243
|
|
|
243
244
|
if ruby?(abspath)
|
|
244
245
|
basename = File.basename(abspath, ".rb")
|
|
245
246
|
return if hidden?(basename)
|
|
246
247
|
|
|
247
|
-
|
|
248
|
-
abspaths << abspath
|
|
248
|
+
paths << [basename, abspath]
|
|
249
249
|
walk_up_from = File.dirname(abspath)
|
|
250
250
|
else
|
|
251
251
|
walk_up_from = abspath
|
|
@@ -260,28 +260,15 @@ module Zeitwerk
|
|
|
260
260
|
basename = File.basename(dir)
|
|
261
261
|
return if hidden?(basename)
|
|
262
262
|
|
|
263
|
-
unless collapse?(dir)
|
|
264
|
-
cnames << inflector.camelize(basename, dir).to_sym
|
|
265
|
-
abspaths << dir
|
|
266
|
-
end
|
|
263
|
+
paths << [basename, abspath] unless collapse?(dir)
|
|
267
264
|
end
|
|
268
265
|
|
|
269
266
|
return unless root_namespace
|
|
270
267
|
|
|
271
|
-
if
|
|
268
|
+
if paths.empty?
|
|
272
269
|
real_mod_name(root_namespace)
|
|
273
270
|
else
|
|
274
|
-
|
|
275
|
-
# problematic one, if any.
|
|
276
|
-
cnames.reverse!
|
|
277
|
-
|
|
278
|
-
cname_validator = Module.new
|
|
279
|
-
cnames.each_with_index do |cname, i|
|
|
280
|
-
cname_validator.const_defined?(cname, false)
|
|
281
|
-
rescue ::NameError
|
|
282
|
-
j = -(i + 1)
|
|
283
|
-
raise Zeitwerk::NameError.new("cannot derive a constant name from #{abspaths[j]}")
|
|
284
|
-
end
|
|
271
|
+
cnames = paths.reverse_each.map { |b, a| cname_for(b, a) }
|
|
285
272
|
|
|
286
273
|
if root_namespace == Object
|
|
287
274
|
cnames.join("::")
|
|
@@ -422,34 +409,15 @@ module Zeitwerk
|
|
|
422
409
|
# @sig (String, Module) -> void
|
|
423
410
|
private def set_autoloads_in_dir(dir, parent)
|
|
424
411
|
ls(dir) do |basename, abspath|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
412
|
+
if ruby?(basename)
|
|
413
|
+
basename.delete_suffix!(".rb")
|
|
414
|
+
autoload_file(parent, cname_for(basename, abspath), abspath)
|
|
415
|
+
else
|
|
416
|
+
if collapse?(abspath)
|
|
417
|
+
set_autoloads_in_dir(abspath, parent)
|
|
430
418
|
else
|
|
431
|
-
|
|
432
|
-
set_autoloads_in_dir(abspath, parent)
|
|
433
|
-
else
|
|
434
|
-
cname = inflector.camelize(basename, abspath).to_sym
|
|
435
|
-
autoload_subdir(parent, cname, abspath)
|
|
436
|
-
end
|
|
419
|
+
autoload_subdir(parent, cname_for(basename, abspath), abspath)
|
|
437
420
|
end
|
|
438
|
-
rescue ::NameError => error
|
|
439
|
-
path_type = ruby?(abspath) ? "file" : "directory"
|
|
440
|
-
|
|
441
|
-
raise NameError.new(<<~MESSAGE, error.name)
|
|
442
|
-
#{error.message} inferred by #{inflector.class} from #{path_type}
|
|
443
|
-
|
|
444
|
-
#{abspath}
|
|
445
|
-
|
|
446
|
-
Possible ways to address this:
|
|
447
|
-
|
|
448
|
-
* Tell Zeitwerk to ignore this particular #{path_type}.
|
|
449
|
-
* Tell Zeitwerk to ignore one of its parent directories.
|
|
450
|
-
* Rename the #{path_type} to comply with the naming conventions.
|
|
451
|
-
* Modify the inflector to handle this case.
|
|
452
|
-
MESSAGE
|
|
453
421
|
end
|
|
454
422
|
end
|
|
455
423
|
end
|
data/lib/zeitwerk/version.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.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Xavier Noria
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-08-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |2
|
|
14
14
|
Zeitwerk implements constant autoloading with Ruby semantics. Each gem
|