zeitwerk 1.3.4 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|