named_imports 0.2.0 → 0.2.1
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/lib/named_imports.rb +71 -49
- data/lib/named_imports/error.rb +35 -0
- data/lib/named_imports/version.rb +1 -1
- 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: bb15d783f22496923d8eb7770bc934347bbd84a0019fad85380e3e43a29361d7
|
|
4
|
+
data.tar.gz: fb90680e03f17db882f40cd38e93e3d51c729177d90e67bc7b6f5d82fd99fe8d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 498ea8dd7a20b2e9a5070e2edfa97b31911b471fa93fe28800ad076f69b031b1132ea5bc65d12db206b52c5bb0dd1903dd41ff611fa1b637cb5aa16947bf0445
|
|
7
|
+
data.tar.gz: 88c609ed4e0649b998752474c78d6496978b1adc5144fe294a0ed770561f0120668977c75885fe8e605748f22a137f08b3d2541becd23e8ab2a92d1c2a9db8f1
|
data/lib/named_imports.rb
CHANGED
|
@@ -1,79 +1,101 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "named_imports/version"
|
|
4
|
+
require_relative "named_imports/error"
|
|
4
5
|
|
|
5
6
|
module NamedImports
|
|
6
|
-
class Error < StandardError; end
|
|
7
|
-
|
|
8
7
|
class << self
|
|
9
|
-
def from(
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
def from(raw_path, constant_names, context = Object)
|
|
9
|
+
into_path, import_line = caller_path_and_line
|
|
10
|
+
from_path = full_path_for_import(from_path: raw_path, into_path: into_path)
|
|
11
|
+
sandbox = sandbox_eval(file_path: from_path)
|
|
12
|
+
load_constants(constant_names, from_sandbox: sandbox, into_context: context)
|
|
13
|
+
end
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
def import(context = Object, &block)
|
|
16
|
+
into_path, import_line = caller_path_and_line
|
|
17
|
+
constant_names = []
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
begin
|
|
20
|
+
block.call
|
|
21
|
+
rescue => e
|
|
22
|
+
constant_name = constant_name_from_error(e)
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
NamedImports.
|
|
24
|
+
if constant_name.nil?
|
|
25
|
+
raise NamedImports::Error::ImportBlockError.new(into_path, import_line, e)
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
context.send(:remove_const, constant_name) if context.const_defined?(constant_name, false)
|
|
29
|
-
context.const_set(constant_name, anon_mod.const_get(constant_name))
|
|
28
|
+
if !constant_names.include?(constant_name)
|
|
29
|
+
constant_names << constant_name
|
|
30
|
+
context.const_set(constant_name, nil)
|
|
30
31
|
end
|
|
32
|
+
|
|
33
|
+
retry
|
|
31
34
|
end
|
|
35
|
+
|
|
36
|
+
constant_names
|
|
32
37
|
end
|
|
33
38
|
|
|
34
|
-
def
|
|
35
|
-
|
|
39
|
+
def make_named_imports_available(in_context: Object)
|
|
40
|
+
def_method = in_context == Object ? :define_method : :define_singleton_method
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
raise e unless /uninitialized constant /.match?(e.message)
|
|
42
|
+
in_context.send(def_method, :from) do |path, constants|
|
|
43
|
+
NamedImports.from(path, constants, in_context)
|
|
44
|
+
end
|
|
41
45
|
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
in_context.send(def_method, :import) do |&block|
|
|
47
|
+
NamedImports.import(in_context, &block)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
raise NameError, "unable to import constant: #{e.message.gsub(/uninitialized constant /, '')}"
|
|
47
|
-
end
|
|
51
|
+
private
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
def caller_path_and_line
|
|
54
|
+
caller_path_info = caller(3..3).first
|
|
55
|
+
caller_path_info.match(/\A(.+?):(\d+):/)[1..2]
|
|
56
|
+
end
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
def full_path_for_import(from_path:, into_path:)
|
|
59
|
+
ext = %r{[^/]+\.[^/]+$}.match?(from_path) ? "" : ".rb"
|
|
60
|
+
from_path_with_ext = "#{from_path}#{ext}"
|
|
61
|
+
importer_dir = File.dirname(into_path)
|
|
62
|
+
File.expand_path(from_path_with_ext, importer_dir)
|
|
63
|
+
end
|
|
55
64
|
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
def catchable_missing_constant_error?(error)
|
|
66
|
+
error.is_a?(NameError) && error.message =~ /uninitialized constant /
|
|
67
|
+
end
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
def constant_name_from_error(error)
|
|
70
|
+
return unless error.is_a?(NameError)
|
|
71
|
+
constant_matcher = /uninitialized constant (?:#<Module:[^>]+>::)?(\w*(?:::\w+)*)$/
|
|
72
|
+
constant_match = error.message.match(constant_matcher)
|
|
73
|
+
constant_match && constant_match[1]
|
|
60
74
|
end
|
|
61
75
|
|
|
62
|
-
|
|
76
|
+
def read_content(file_path:)
|
|
77
|
+
File.open(file_path, &:read)
|
|
78
|
+
end
|
|
63
79
|
|
|
64
|
-
def
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
def sandbox_eval(file_path:)
|
|
81
|
+
sandbox_module = Module.new
|
|
82
|
+
make_named_imports_available(in_context: sandbox_module)
|
|
83
|
+
ruby_code = read_content(file_path: file_path)
|
|
84
|
+
sandbox_module.class_eval(ruby_code, file_path)
|
|
85
|
+
sandbox_module
|
|
69
86
|
end
|
|
70
|
-
end
|
|
71
87
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
88
|
+
def load_constants(constant_names, from_sandbox:, into_context:)
|
|
89
|
+
constant_names.each do |constant_name|
|
|
90
|
+
if into_context.const_defined?(constant_name, false)
|
|
91
|
+
into_context.send(:remove_const, constant_name)
|
|
92
|
+
end
|
|
75
93
|
|
|
76
|
-
|
|
77
|
-
|
|
94
|
+
sandboxed_constant = from_sandbox.const_get(constant_name)
|
|
95
|
+
into_context.const_set(constant_name, sandboxed_constant)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
78
98
|
end
|
|
99
|
+
|
|
100
|
+
make_named_imports_available
|
|
79
101
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NamedImports
|
|
4
|
+
module Error
|
|
5
|
+
class Base < ::StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class ImportBlockError < NamedImports::Error::Base
|
|
9
|
+
def initialize(importer_file, importer_line, original_error = nil)
|
|
10
|
+
error_details = []
|
|
11
|
+
error_details << "Something went wrong when evaluating the named import at #{importer_file}:#{importer_line}."
|
|
12
|
+
error_details << "This is likely to be an error in your 'import' block."
|
|
13
|
+
if original_error
|
|
14
|
+
original_error_class = original_error.class.to_s
|
|
15
|
+
article = original_error_class[0].match(/aeiou/i) ? "an" : "a"
|
|
16
|
+
error_details << "The original error was #{article} #{original_error_class}: #{original_error.message}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
error_message = error_details.join(" ")
|
|
20
|
+
super(error_message)
|
|
21
|
+
|
|
22
|
+
set_backtrace(original_error.backtrace) if original_error
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class ImportError < ::NameError
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class ConstantImportError < NamedImports::Error::ImportError
|
|
30
|
+
def initialize(imported_name, imported_file, importer_file, importer_line)
|
|
31
|
+
super("Unable to import #{imported_name} from #{imported_file} (import occurs in #{importer_file}:#{importer_line})")
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: named_imports
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Keegan Leitz
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-03-
|
|
11
|
+
date: 2021-03-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -156,6 +156,7 @@ files:
|
|
|
156
156
|
- bin/console
|
|
157
157
|
- bin/setup
|
|
158
158
|
- lib/named_imports.rb
|
|
159
|
+
- lib/named_imports/error.rb
|
|
159
160
|
- lib/named_imports/version.rb
|
|
160
161
|
- named_imports.gemspec
|
|
161
162
|
homepage: https://github.com/kjleitz/named_imports
|