zeitwerk 1.3.4 → 1.4.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 +4 -4
- data/README.md +8 -1
- data/lib/zeitwerk/explicit_namespace.rb +4 -0
- data/lib/zeitwerk/loader.rb +38 -19
- data/lib/zeitwerk/loader/callbacks.rb +2 -2
- 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: a7e867060d3bf347938f153335a463ddbb48995f70f3aed8472a6641e2592a71
|
4
|
+
data.tar.gz: af10438f14e119bf184133b1c1734e01fbe61954ce2128805a1ab941125dc4cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a744a32914b0bd02c07842b448770512d6a8aad66b5524bbe9bb6ef854faeea1ce11e2090bc9a968aebb3501d54de54f65f7927f9d26d4f365a13ad806920e38
|
7
|
+
data.tar.gz: 032c50fd06d88be03ee5fae4d7fd6bdbd34780b5dc1f978a8a63a3a9bdda960d417dcb91b40bb82865d3c58b6751cf58506c1bed2454c65c14c6c1d2b5f7bdc7
|
data/README.md
CHANGED
@@ -216,7 +216,14 @@ Zeitwerk instances are able to eager load their managed files:
|
|
216
216
|
loader.eager_load
|
217
217
|
```
|
218
218
|
|
219
|
-
That skips ignored files and directories
|
219
|
+
That skips [ignored files and directories](#ignoring-parts-of-the-project), and you can also tell Zeitwerk that certain files or directories are autoloadable, but should not be eager loaded:
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
db_adapters = "#{__dir__}/my_gem/db_adapters"
|
223
|
+
loader.do_not_eager_load(db_adapters)
|
224
|
+
loader.setup
|
225
|
+
loader.eager_load # won't eager load the database adapters
|
226
|
+
```
|
220
227
|
|
221
228
|
Eager loading is synchronized and idempotent.
|
222
229
|
|
@@ -57,6 +57,10 @@ module Zeitwerk
|
|
57
57
|
@cpaths = {}
|
58
58
|
@mutex = Mutex.new
|
59
59
|
@tracer = TracePoint.new(:class) do |event|
|
60
|
+
# If the class is a singleton class, we won't do anything with it so we can bail out immediately.
|
61
|
+
# This is several orders of magnitude faster than accessing `Module#name`.
|
62
|
+
next if event.self.singleton_class?
|
63
|
+
|
60
64
|
# Note that it makes sense to compute the hash code unconditionally,
|
61
65
|
# because the trace point is disabled if cpaths is empty.
|
62
66
|
if loader = cpaths.delete(event.self.name)
|
data/lib/zeitwerk/loader.rb
CHANGED
@@ -57,7 +57,7 @@ module Zeitwerk
|
|
57
57
|
#
|
58
58
|
# A shadowed file is a file managed by this autoloader that is skipped
|
59
59
|
# because its matching constant path has already been seen. Think $LOAD_PATH
|
60
|
-
#
|
60
|
+
# and require, only the first occurrence of a given relative name is loaded.
|
61
61
|
#
|
62
62
|
# If the existing occurrence is an autoload, we map the file name to the
|
63
63
|
# shadowing autoload path. If the existing occurrence is an already defined
|
@@ -66,7 +66,7 @@ module Zeitwerk
|
|
66
66
|
#
|
67
67
|
# @private
|
68
68
|
# @return [{String => String}]
|
69
|
-
attr_reader :
|
69
|
+
attr_reader :shadowed_files
|
70
70
|
|
71
71
|
# Maps real absolute paths for which an autoload has been set to their
|
72
72
|
# corresponding parent class or module and constant name.
|
@@ -83,7 +83,7 @@ module Zeitwerk
|
|
83
83
|
#
|
84
84
|
# @private
|
85
85
|
# @return [Set<String>]
|
86
|
-
attr_reader :
|
86
|
+
attr_reader :loaded_cpaths
|
87
87
|
|
88
88
|
# Maps constant paths of namespaces to arrays of corresponding directories.
|
89
89
|
#
|
@@ -103,6 +103,12 @@ module Zeitwerk
|
|
103
103
|
# @return [{String => <String>}]
|
104
104
|
attr_reader :lazy_subdirs
|
105
105
|
|
106
|
+
# Absolute paths of files or directories not to be eager loaded.
|
107
|
+
#
|
108
|
+
# @private
|
109
|
+
# @return [Set<String>]
|
110
|
+
attr_reader :eager_load_exclusions
|
111
|
+
|
106
112
|
# @private
|
107
113
|
# @return [Mutex]
|
108
114
|
attr_reader :mutex
|
@@ -114,14 +120,15 @@ module Zeitwerk
|
|
114
120
|
@inflector = Inflector.new
|
115
121
|
@logger = self.class.default_logger
|
116
122
|
|
117
|
-
@root_dirs
|
118
|
-
@preloads
|
119
|
-
@ignored
|
120
|
-
@ignored_paths
|
121
|
-
@autoloads
|
122
|
-
@
|
123
|
-
@lazy_subdirs
|
124
|
-
@
|
123
|
+
@root_dirs = {}
|
124
|
+
@preloads = []
|
125
|
+
@ignored = Set.new
|
126
|
+
@ignored_paths = Set.new
|
127
|
+
@autoloads = {}
|
128
|
+
@loaded_cpaths = Set.new
|
129
|
+
@lazy_subdirs = {}
|
130
|
+
@shadowed_files = {}
|
131
|
+
@eager_load_exclusions = Set.new
|
125
132
|
|
126
133
|
@mutex = Mutex.new
|
127
134
|
@setup = false
|
@@ -230,9 +237,9 @@ module Zeitwerk
|
|
230
237
|
end
|
231
238
|
|
232
239
|
autoloads.clear
|
233
|
-
|
240
|
+
loaded_cpaths.clear
|
234
241
|
lazy_subdirs.clear
|
235
|
-
|
242
|
+
shadowed_files.clear
|
236
243
|
|
237
244
|
Registry.on_unload(self)
|
238
245
|
ExplicitNamespace.unregister(self)
|
@@ -255,18 +262,21 @@ module Zeitwerk
|
|
255
262
|
|
256
263
|
# Eager loads all files in the root directories, recursively. Files do not
|
257
264
|
# need to be in `$LOAD_PATH`, absolute file names are used. Ignored files
|
258
|
-
# are not eager loaded.
|
265
|
+
# are not eager loaded. You can opt-out specifically in specific files and
|
266
|
+
# directories with `do_not_eager_load`.
|
259
267
|
#
|
260
268
|
# @return [void]
|
261
269
|
def eager_load
|
262
270
|
mutex.synchronize do
|
263
271
|
break if @eager_loaded
|
264
272
|
|
265
|
-
queue = non_ignored_root_dirs
|
273
|
+
queue = non_ignored_root_dirs.reject { |dir| eager_load_exclusions.member?(dir) }
|
266
274
|
while dir = queue.shift
|
267
275
|
each_abspath(dir) do |abspath|
|
276
|
+
next if eager_load_exclusions.member?(abspath)
|
277
|
+
|
268
278
|
if ruby?(abspath)
|
269
|
-
require abspath unless
|
279
|
+
require abspath unless shadowed_files.key?(abspath)
|
270
280
|
elsif dir?(abspath)
|
271
281
|
queue << abspath
|
272
282
|
end
|
@@ -277,12 +287,21 @@ module Zeitwerk
|
|
277
287
|
end
|
278
288
|
end
|
279
289
|
|
290
|
+
# Let eager load ignore the given files or directories. The constants
|
291
|
+
# defined in those files are still autoloadable.
|
292
|
+
#
|
293
|
+
# @param paths [<String, Pathname, <String, Pathname>>]
|
294
|
+
# @return [void]
|
295
|
+
def do_not_eager_load(*paths)
|
296
|
+
mutex.synchronize { eager_load_exclusions.merge(expand_paths(paths)) }
|
297
|
+
end
|
298
|
+
|
280
299
|
# Says if the given constant path has been loaded.
|
281
300
|
#
|
282
301
|
# @param cpath [String]
|
283
302
|
# @return [Boolean]
|
284
303
|
def loaded?(cpath)
|
285
|
-
|
304
|
+
loaded_cpaths.member?(cpath)
|
286
305
|
end
|
287
306
|
|
288
307
|
# --- Class methods ---------------------------------------------------------------------------
|
@@ -387,7 +406,7 @@ module Zeitwerk
|
|
387
406
|
def autoload_file(parent, cname, file)
|
388
407
|
if autoload_path = autoload_for?(parent, cname)
|
389
408
|
# First autoload for a Ruby file wins, just ignore subsequent ones.
|
390
|
-
|
409
|
+
shadowed_files[file] = autoload_path and return if ruby?(autoload_path)
|
391
410
|
|
392
411
|
# Override autovivification, we want the namespace to become the
|
393
412
|
# class/module defined in this file.
|
@@ -397,7 +416,7 @@ module Zeitwerk
|
|
397
416
|
set_autoload(parent, cname, file)
|
398
417
|
register_explicit_namespace(cpath(parent, cname))
|
399
418
|
elsif cdef?(parent, cname)
|
400
|
-
|
419
|
+
shadowed_files[file] = cpath(parent, cname)
|
401
420
|
else
|
402
421
|
set_autoload(parent, cname, file)
|
403
422
|
end
|
@@ -6,7 +6,7 @@ module Zeitwerk::Loader::Callbacks
|
|
6
6
|
# @return [void]
|
7
7
|
def on_file_autoloaded(file)
|
8
8
|
parent, cname = autoloads[file]
|
9
|
-
|
9
|
+
loaded_cpaths.add(cpath(parent, cname))
|
10
10
|
log("constant #{cpath(parent, cname)} loaded from file #{file}") if logger
|
11
11
|
end
|
12
12
|
|
@@ -22,7 +22,7 @@ module Zeitwerk::Loader::Callbacks
|
|
22
22
|
autovivified_module = parent.const_set(cname, Module.new)
|
23
23
|
log("module #{autovivified_module.name} autovivified from directory #{dir}") if logger
|
24
24
|
|
25
|
-
|
25
|
+
loaded_cpaths.add(autovivified_module.name)
|
26
26
|
on_namespace_loaded(autovivified_module)
|
27
27
|
end
|
28
28
|
|
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: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xavier Noria
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-03-
|
11
|
+
date: 2019-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2
|
14
14
|
Zeitwerk implements constant autoloading with Ruby semantics. Each gem
|