import_from 0.1.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.
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Kernel extensions providing Python-like import syntax for Ruby.
4
+ module Kernel
5
+ # Imports constants from a gem into an isolated Ruby::Box namespace
6
+ #
7
+ # This method creates a new isolated Ruby::Box, loads the specified gem
8
+ # within that box, and extracts requested constants into the Object namespace.
9
+ # This prevents namespace collisions and allows multiple versions of gems
10
+ # to coexist.
11
+ #
12
+ # @api public
13
+ #
14
+ # @example Import specific classes from a gem
15
+ # from 'active_support', import: 'HashWithIndifferentAccess'
16
+ # HashWithIndifferentAccess.new # => Available in global namespace
17
+ #
18
+ # @example Import multiple constants
19
+ # from 'my_gem', import: ['User', 'Post']
20
+ #
21
+ # @example Import all constants with wildcard and alias the box
22
+ # from 'my_gem', import: '*', as: :MyGem
23
+ # MyGem.const_get('User') # => Access via box
24
+ #
25
+ # @example Import from relative path
26
+ # from './lib/my_module', import: 'MyClass'
27
+ #
28
+ # @param gem_name [String] The name of the gem to load, or a relative path starting with '.'
29
+ # @param import [String, Array<String>] The constant name(s) to import, or '*' for wildcard import
30
+ # @param as [Symbol, String, nil] Optional alias name to assign the Ruby::Box instance to
31
+ #
32
+ # @return [Object, Array<Object>, Ruby::Box] Returns the imported constant, an array of constants if multiple, or the
33
+ # Ruby::Box if wildcard import
34
+ #
35
+ # @raise [NameError] If the requested constant does not exist in the gem
36
+ #
37
+ # @raise [LoadError] If the gem cannot be loaded
38
+ #
39
+ def from(gem_name, import:, as: nil)
40
+ # Create a new isolated box
41
+ box = Ruby::Box.new
42
+
43
+ require 'bundler/setup'
44
+
45
+ # Copy the load path into the box
46
+ $LOAD_PATH.each do |path|
47
+ # $LOAD_PATH << path
48
+ box.eval("$LOAD_PATH << #{path.inspect}")
49
+ end
50
+
51
+ # Load the library into the box
52
+ # If it's a relative path, use require_relative, otherwise require
53
+ if gem_name.start_with?('.')
54
+ box.require_relative(gem_name)
55
+ else
56
+ require gem_name
57
+ box.require(gem_name)
58
+ end
59
+
60
+ Object.const_set(as, box) if as
61
+
62
+ return box if import == '*'
63
+
64
+ # Extract the requested constants
65
+ targets = Array(import)
66
+ results = targets.map do |const_name|
67
+ # Fetch the constant from the box namespace
68
+ klass = box.const_get(const_name)
69
+
70
+ # Inject the constant into the caller's namespace (Object by default)
71
+ # This makes it look like it was imported globally/locally
72
+ Object.const_set(const_name, klass)
73
+ klass
74
+ end
75
+
76
+ results.size == 1 ? results.first : results
77
+ end
78
+
79
+ # Imports constants with Python-style syntax supporting flexible parameter order
80
+ #
81
+ # This method provides a more Pythonic interface to the +from+ method, allowing
82
+ # either "import 'gem_name'" to import entire namespaces or "import 'Class', from: 'gem_name'"
83
+ # to import specific constants.
84
+ #
85
+ # @api public
86
+ #
87
+ # @example Import entire gem namespace
88
+ # import 'active_support', as: :AS
89
+ # AS.const_get('HashWithIndifferentAccess')
90
+ #
91
+ # @example Import specific constants from a gem
92
+ # import ['User', 'Post'], from: 'my_gem'
93
+ #
94
+ # @example Import with alias
95
+ # import 'MyClass', from: 'my_gem', as: :MyAlias
96
+ #
97
+ # @param imports [String, Array<String>] The gem name (when from: is nil) or constant name(s) to import
98
+ # @param from [String, nil] The gem name to import from, or nil to import entire namespace
99
+ # @param as [Symbol, String, nil] Optional alias name for the imported constant or Ruby::Box
100
+ #
101
+ # @return [Object, Array<Object>, Ruby::Box] Returns the imported constant(s) or Ruby::Box instance
102
+ #
103
+ # @raise [NameError] If the requested constant does not exist in the gem
104
+ #
105
+ # @raise [LoadError] If the gem cannot be loaded
106
+ #
107
+ def import(imports, from: nil, as: nil)
108
+ if from.nil?
109
+ from(imports, import: '*', as: as)
110
+ else
111
+ from(from, import: imports, as: as)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImportFrom
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'import_from/version'
4
+ require_relative 'import_from/core_ext/kernel'
5
+
6
+ ENV['RUBY_BOX'] = '1' unless Ruby::Box.enabled?
7
+
8
+ # Entry point
9
+ module ImportFrom
10
+ end
data/mise.toml ADDED
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ ruby = "4.0.0"
@@ -0,0 +1,4 @@
1
+ module ImportFrom
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: import_from
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Wilson Silva
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: A Ruby gem that provides a Python-like syntax for importing modules from
13
+ Ruby gems and files, making it easier to manage dependencies and imports in your
14
+ Ruby applications.
15
+ email:
16
+ - wilson.dsigns@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".claude/commands/document.md"
22
+ - ".claude/commands/gemfile/update.md"
23
+ - ".claude/commands/test.md"
24
+ - ".claude/docs/yard.md"
25
+ - ".claude/settings.local.json"
26
+ - ".editorconfig"
27
+ - ".env"
28
+ - ".overcommit.yml"
29
+ - ".rspec"
30
+ - ".rubocop.yml"
31
+ - ".yardstick.yml"
32
+ - AGENTS.md
33
+ - CHANGELOG.md
34
+ - CLAUDE.md
35
+ - CODE_OF_CONDUCT.md
36
+ - Guardfile
37
+ - LICENSE.txt
38
+ - README.md
39
+ - Rakefile
40
+ - Steepfile
41
+ - docs/ruby-box.md
42
+ - docs/todo.md
43
+ - examples/Gemfile
44
+ - examples/Gemfile.lock
45
+ - examples/README.md
46
+ - examples/from_x_import_star.rb
47
+ - examples/from_x_import_star_as_y.rb
48
+ - examples/from_x_import_y.rb
49
+ - examples/from_x_import_y_as_z.rb
50
+ - examples/from_x_y_import_a.rb
51
+ - examples/from_x_y_import_a_as_b.rb
52
+ - examples/import_x.rb
53
+ - examples/import_x_as_y.rb
54
+ - examples/import_x_as_y_scoped.rb
55
+ - examples/import_x_y_z.rb
56
+ - lib/import_from.rb
57
+ - lib/import_from/core_ext/kernel.rb
58
+ - lib/import_from/version.rb
59
+ - mise.toml
60
+ - sig/import_from.rbs
61
+ homepage: https://github.com/wilsonsilva/import_from
62
+ licenses:
63
+ - MIT
64
+ metadata:
65
+ homepage_uri: https://github.com/wilsonsilva/import_from
66
+ source_code_uri: https://github.com/wilsonsilva/import_from
67
+ changelog_uri: https://github.com/wilsonsilva/import_from/blob/main/CHANGELOG.md
68
+ rubygems_mfa_required: 'true'
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 4.0.0
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubygems_version: 4.0.3
84
+ specification_version: 4
85
+ summary: Provides a Python-like syntax for importing modules from Ruby gems and files.
86
+ test_files: []