zeitwerk 2.5.0.beta6 → 2.5.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74d74bec1f4963cc5d04f037e14723408ae5d1f8c4df16f31f2901402e3230ed
4
- data.tar.gz: 3ebd7f860583cc7a560360b2e766193dc0c74c5cd902c7cb632a614e32dc68e7
3
+ metadata.gz: 8e0d44c224600274a41893cc27d119539f5d625c3be6ed46a54052d9b139c58c
4
+ data.tar.gz: 16c701ed5717318fab08631a001a7c067f81a2027fabbfe4b6a0f6775da60a7d
5
5
  SHA512:
6
- metadata.gz: f0bec92696285efb5ad1f76094b71a4de5a38a0665b493737c945623042b4d744be2c58f4006ed5c8c4abe0ccb70854c94ba63c3b7eeef1a5ae47086a956668d
7
- data.tar.gz: a1392b3b73dcd85769f793aeca9a9d10cb50c70259d88761574c1e62e201b24f32d7122eda587af6017dea93fca27ce9463e5f0dae7b98523d3edba2c13802eb
6
+ metadata.gz: d897fb5bdfc8b27080dbcd6160945e4a4cec6fb0f31c4eb21cd448ec26d1291ad373696995aaddcf4e387b7d731fbe4530b43f3b77f97159ba69bed447f07ade
7
+ data.tar.gz: 3cc2dbbc0840f2d420eb32ed725aaf24b7d889d989060211a9877703b44b6e71fa1d1884df2f50cfbf121b1954cf51db7e867232cde7470698fdb7e408c1be23
data/README.md CHANGED
@@ -50,8 +50,8 @@
50
50
  - [Rules of thumb](#rules-of-thumb)
51
51
  - [Debuggers](#debuggers)
52
52
  - [debug.rb](#debugrb)
53
- - [Break](#break)
54
53
  - [Byebug](#byebug)
54
+ - [Break](#break)
55
55
  - [Pronunciation](#pronunciation)
56
56
  - [Supported Ruby versions](#supported-ruby-versions)
57
57
  - [Testing](#testing)
@@ -810,7 +810,9 @@ Kernel.module_eval do
810
810
  end
811
811
  ```
812
812
 
813
- That file does not define a constant path after the path name and you need to tell Zeitwerk:
813
+ `Kernel` is already defined by Ruby so the module cannot be autoloaded. Also, that file does not define a constant path after the path name. Therefore, Zeitwerk should not process it at all.
814
+
815
+ The extension can still coexist with the rest of the project, you only need to tell Zeitwerk to ignore it:
814
816
 
815
817
  ```ruby
816
818
  kernel_ext = "#{__dir__}/my_gem/core_ext/kernel.rb"
@@ -826,6 +828,14 @@ loader.ignore(core_ext)
826
828
  loader.setup
827
829
  ```
828
830
 
831
+ Now, that file has to be loaded manually with `require` or `require_relative`:
832
+
833
+ ```ruby
834
+ require_relative "my_gem/core_ext/kernel"
835
+ ```
836
+
837
+ and you can do that anytime, before configuring the loader, or after configuring the loader, does not matter.
838
+
829
839
  <a id="markdown-use-case-the-adapter-pattern" name="use-case-the-adapter-pattern"></a>
830
840
  #### Use case: The adapter pattern
831
841
 
@@ -973,17 +983,19 @@ With that, when Zeitwerk scans the file system and reaches the gem directories `
973
983
  <a id="markdown-debugrb" name="debugrb"></a>
974
984
  #### debug.rb
975
985
 
976
- The new [debug.rb](https://github.com/ruby/debug) gem and Zeitwerk seem to be compatible, as far as I can tell. This is the new debugger that is going to ship with Ruby 3.1.
986
+ The new [debug.rb](https://github.com/ruby/debug) gem and Zeitwerk are mostly compatible. This is the new debugger that is going to ship with Ruby 3.1.
977
987
 
978
- <a id="markdown-break" name="break"></a>
979
- #### Break
980
-
981
- Zeitwerk works fine with [@gsamokovarov](https://github.com/gsamokovarov)'s [Break](https://github.com/gsamokovarov/break) debugger.
988
+ There's one exception, though: Due to a technical limitation of tracepoints, explicit namespaces are not autoloaded while expressions are evaluated in the REPL. See [ruby/debug#408](https://github.com/ruby/debug/issues/408).
982
989
 
983
990
  <a id="markdown-byebug" name="byebug"></a>
984
991
  #### Byebug
985
992
 
986
- Zeitwerk and [Byebug](https://github.com/deivid-rodriguez/byebug) are incompatible, classes or modules that belong to [explicit namespaces](#explicit-namespaces) are not autoloaded inside a Byebug session. See [this issue](https://github.com/deivid-rodriguez/byebug/issues/564#issuecomment-499413606) for further details.
993
+ Zeitwerk and [Byebug](https://github.com/deivid-rodriguez/byebug) have a similar edge incompatibility.
994
+
995
+ <a id="markdown-break" name="break"></a>
996
+ #### Break
997
+
998
+ Zeitwerk works fine with [@gsamokovarov](https://github.com/gsamokovarov)'s [Break](https://github.com/gsamokovarov/break) debugger.
987
999
 
988
1000
  <a id="markdown-pronunciation" name="pronunciation"></a>
989
1001
  ## Pronunciation
@@ -24,22 +24,22 @@ module Kernel
24
24
  def require(path)
25
25
  if loader = Zeitwerk::Registry.loader_for(path)
26
26
  if path.end_with?(".rb")
27
- zeitwerk_original_require(path).tap do |required|
28
- loader.on_file_autoloaded(path) if required
29
- end
27
+ required = zeitwerk_original_require(path)
28
+ loader.on_file_autoloaded(path) if required
29
+ required
30
30
  else
31
31
  loader.on_dir_autoloaded(path)
32
32
  true
33
33
  end
34
34
  else
35
- zeitwerk_original_require(path).tap do |required|
36
- if required
37
- abspath = $LOADED_FEATURES.last
38
- if loader = Zeitwerk::Registry.loader_for(abspath)
39
- loader.on_file_autoloaded(abspath)
40
- end
35
+ required = zeitwerk_original_require(path)
36
+ if required
37
+ abspath = $LOADED_FEATURES.last
38
+ if loader = Zeitwerk::Registry.loader_for(abspath)
39
+ loader.on_file_autoloaded(abspath)
41
40
  end
42
41
  end
42
+ required
43
43
  end
44
44
  end
45
45
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "set"
4
- require "securerandom"
5
4
 
6
5
  module Zeitwerk
7
6
  class Loader
@@ -14,22 +13,16 @@ module Zeitwerk
14
13
  include Helpers
15
14
  include Config
16
15
 
17
- # Keeps track of autoloads defined by the loader which have not been
18
- # executed so far.
16
+ # Maps absolute paths for which an autoload has been set ---and not
17
+ # executed--- to their corresponding parent class or module and constant
18
+ # name.
19
19
  #
20
- # This metadata helps us implement a few things:
21
- #
22
- # 1. When autoloads are triggered, ensure they define the expected constant
23
- # and invoke user callbacks. If reloading is enabled, remember cref and
24
- # abspath for later unloading logic.
25
- #
26
- # 2. When unloading, remove autoloads that have not been executed.
27
- #
28
- # 3. Eager load with a recursive const_get, rather than a recursive require,
29
- # for consistency with lazy loading.
20
+ # "/Users/fxn/blog/app/models/user.rb" => [Object, :User],
21
+ # "/Users/fxn/blog/app/models/hotel/pricing.rb" => [Hotel, :Pricing]
22
+ # ...
30
23
  #
31
24
  # @private
32
- # @sig Zeitwerk::Autoloads
25
+ # @sig Hash[String, [Module, Symbol]]
33
26
  attr_reader :autoloads
34
27
 
35
28
  # We keep track of autoloaded directories to remove them from the registry
@@ -87,7 +80,7 @@ module Zeitwerk
87
80
  def initialize
88
81
  super
89
82
 
90
- @autoloads = Autoloads.new
83
+ @autoloads = {}
91
84
  @autoloaded_dirs = []
92
85
  @to_unload = {}
93
86
  @lazy_subdirs = Hash.new { |h, cpath| h[cpath] = [] }
@@ -138,7 +131,7 @@ module Zeitwerk
138
131
  # is enough.
139
132
  unloaded_files = Set.new
140
133
 
141
- autoloads.each do |(parent, cname), abspath|
134
+ autoloads.each do |abspath, (parent, cname)|
142
135
  if parent.autoload?(cname)
143
136
  unload_autoload(parent, cname)
144
137
  else
@@ -234,7 +227,7 @@ module Zeitwerk
234
227
  next if honour_exclusions && excluded_from_eager_load?(abspath)
235
228
 
236
229
  if ruby?(abspath)
237
- if cref = autoloads.cref_for(abspath)
230
+ if cref = autoloads[abspath]
238
231
  cget(*cref)
239
232
  end
240
233
  elsif dir?(abspath) && !root_dirs.key?(abspath)
@@ -376,7 +369,7 @@ module Zeitwerk
376
369
 
377
370
  # @sig (Module, Symbol, String) -> void
378
371
  def autoload_subdir(parent, cname, subdir)
379
- if autoload_path = autoloads.abspath_for(parent, cname)
372
+ if autoload_path = autoload_path_set_by_me_for?(parent, cname)
380
373
  cpath = cpath(parent, cname)
381
374
  register_explicit_namespace(cpath) if ruby?(autoload_path)
382
375
  # We do not need to issue another autoload, the existing one is enough
@@ -432,7 +425,7 @@ module Zeitwerk
432
425
 
433
426
  # @sig (Module, Symbol, String) -> void
434
427
  def set_autoload(parent, cname, abspath)
435
- autoloads.define(parent, cname, abspath)
428
+ parent.autoload(cname, abspath)
436
429
 
437
430
  if logger
438
431
  if ruby?(abspath)
@@ -442,6 +435,7 @@ module Zeitwerk
442
435
  end
443
436
  end
444
437
 
438
+ autoloads[abspath] = [parent, cname]
445
439
  Registry.register_autoload(self, abspath)
446
440
 
447
441
  # See why in the documentation of Zeitwerk::Registry.inceptions.
@@ -450,6 +444,15 @@ module Zeitwerk
450
444
  end
451
445
  end
452
446
 
447
+ # @sig (Module, Symbol) -> String?
448
+ def autoload_path_set_by_me_for?(parent, cname)
449
+ if autoload_path = strict_autoload_path(parent, cname)
450
+ autoload_path if autoloads.key?(autoload_path)
451
+ else
452
+ Registry.inception?(cpath(parent, cname))
453
+ end
454
+ end
455
+
453
456
  # @sig (String) -> void
454
457
  def register_explicit_namespace(cpath)
455
458
  ExplicitNamespace.register(cpath, self)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Zeitwerk
4
- VERSION = "2.5.0.beta6"
4
+ VERSION = "2.5.3"
5
5
  end
data/lib/zeitwerk.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  module Zeitwerk
4
4
  require_relative "zeitwerk/real_mod_name"
5
5
  require_relative "zeitwerk/loader"
6
- require_relative "zeitwerk/autoloads"
7
6
  require_relative "zeitwerk/registry"
8
7
  require_relative "zeitwerk/explicit_namespace"
9
8
  require_relative "zeitwerk/inflector"
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.5.0.beta6
4
+ version: 2.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Xavier Noria
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-14 00:00:00.000000000 Z
11
+ date: 2021-12-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  Zeitwerk implements constant autoloading with Ruby semantics. Each gem
@@ -23,7 +23,6 @@ files:
23
23
  - MIT-LICENSE
24
24
  - README.md
25
25
  - lib/zeitwerk.rb
26
- - lib/zeitwerk/autoloads.rb
27
26
  - lib/zeitwerk/error.rb
28
27
  - lib/zeitwerk/explicit_namespace.rb
29
28
  - lib/zeitwerk/gem_inflector.rb
@@ -55,9 +54,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
55
54
  version: '2.5'
56
55
  required_rubygems_version: !ruby/object:Gem::Requirement
57
56
  requirements:
58
- - - ">"
57
+ - - ">="
59
58
  - !ruby/object:Gem::Version
60
- version: 1.3.1
59
+ version: '0'
61
60
  requirements: []
62
61
  rubygems_version: 3.2.22
63
62
  signing_key:
@@ -1,71 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Zeitwerk
4
- # @private
5
- class Autoloads
6
- # Maps crefs for which an autoload has been defined to the corresponding
7
- # absolute path.
8
- #
9
- # [Object, :User] => "/Users/fxn/blog/app/models/user.rb"
10
- # [Object, :Hotel] => "/Users/fxn/blog/app/models/hotel"
11
- # ...
12
- #
13
- # This colection is transient, callbacks delete its entries as autoloads get
14
- # executed.
15
- #
16
- # @sig Hash[[Module, Symbol], String]
17
- attr_reader :c2a
18
-
19
- # This is the inverse of c2a, for inverse lookups.
20
- #
21
- # @sig Hash[String, [Module, Symbol]]
22
- attr_reader :a2c
23
-
24
- # @sig () -> void
25
- def initialize
26
- @c2a = {}
27
- @a2c = {}
28
- end
29
-
30
- # @sig (Module, Symbol, String) -> void
31
- def define(parent, cname, abspath)
32
- parent.autoload(cname, abspath)
33
- cref = [parent, cname]
34
- c2a[cref] = abspath
35
- a2c[abspath] = cref
36
- end
37
-
38
- # @sig () { () -> [[Module, Symbol], String] } -> void
39
- def each(&block)
40
- c2a.each(&block)
41
- end
42
-
43
- # @sig (Module, Symbol) -> String?
44
- def abspath_for(parent, cname)
45
- c2a[[parent, cname]]
46
- end
47
-
48
- # @sig (String) -> [Module, Symbol]?
49
- def cref_for(abspath)
50
- a2c[abspath]
51
- end
52
-
53
- # @sig (String) -> [Module, Symbol]?
54
- def delete(abspath)
55
- cref = a2c.delete(abspath)
56
- c2a.delete(cref)
57
- cref
58
- end
59
-
60
- # @sig () -> void
61
- def clear
62
- c2a.clear
63
- a2c.clear
64
- end
65
-
66
- # @sig () -> bool
67
- def empty?
68
- c2a.empty? && a2c.empty?
69
- end
70
- end
71
- end