modulation 0.11 → 0.12
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/CHANGELOG.md +56 -0
- data/README.md +11 -8
- data/lib/modulation.rb +4 -0
- data/lib/modulation/core.rb +27 -9
- data/lib/modulation/paths.rb +37 -14
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72f329f0720d40aea09237c6cce4dc9eeb5ccfd3a94d78ae7d9ce956ea016051
|
4
|
+
data.tar.gz: 1541fdfbef9bec5ab3b7f6ed14a5eb7445f01b9c240baaf89b77959b9e0ffcfe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb267ba2a1a29119346c0ccd9d001f77614945a43c4e7006b5d4900f9de9812e4afff393ec3eb7c1ffb9bf5e2ba539ef51e4811bbd203b08e66602711bb57856
|
7
|
+
data.tar.gz: 5fbb09abc67eaa52d345f3c9d828a46a1bcd0b77f7a36317e9d2c81e5465009bc537df80ce437c1ed64ca01e61cf1883381531206d60856a916c9a6d73562c1b
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
## [0.12] 2018-08-20
|
2
|
+
|
3
|
+
* Fix sanitizing of error backtrace.
|
4
|
+
* Fix importing of gems.
|
5
|
+
|
6
|
+
## [0.11] 2018-08-20
|
7
|
+
|
8
|
+
* Add Modulation.mock for use in testing.
|
9
|
+
|
10
|
+
## [0.10] 2018-08-19
|
11
|
+
|
12
|
+
* Refactor and cleanup code.
|
13
|
+
|
14
|
+
## [0.9.1] 2018-08-15
|
15
|
+
|
16
|
+
* Small fixes to README.
|
17
|
+
|
18
|
+
## [0.9] 2018-08-13
|
19
|
+
|
20
|
+
* Add support for module reloading.
|
21
|
+
|
22
|
+
## [0.8] 2018-08-05
|
23
|
+
|
24
|
+
* Add support for nested namespaces.
|
25
|
+
* Add support for circular dependencies.
|
26
|
+
|
27
|
+
## [0.7] 2018-07-29
|
28
|
+
|
29
|
+
* Add `MODULE` constant for accessing module from nested namespaces within itself
|
30
|
+
|
31
|
+
## [0.6] 2018-07-23
|
32
|
+
|
33
|
+
* Add support for using gems as imported modules (experimental feature)
|
34
|
+
* Add Modulation.full_trace! method for getting full backtrace on errors
|
35
|
+
* Fix Modulation.transform_export_default_value
|
36
|
+
* Change name to *Modulation*
|
37
|
+
|
38
|
+
## [0.5.1] 2018-07-20
|
39
|
+
|
40
|
+
* Fix extend_from, include_from to work with ruby 2.4
|
41
|
+
|
42
|
+
## [0.5] 2018-07-19
|
43
|
+
|
44
|
+
* Add extend_from, include_from to include imported methods in classes and modules
|
45
|
+
|
46
|
+
## [0.4] 2018-07-19
|
47
|
+
|
48
|
+
* Refactor code
|
49
|
+
* Add tests
|
50
|
+
* Remove namespace feature (owing to the way Ruby handles constants in blocks)
|
51
|
+
|
52
|
+
## [0.3.3] 2018-07-09
|
53
|
+
|
54
|
+
* Switch to explicit exports
|
55
|
+
* More documentation
|
56
|
+
* Better error handling
|
data/README.md
CHANGED
@@ -393,14 +393,17 @@ end
|
|
393
393
|
|
394
394
|
Gems written using modulation can also be loaded using `import`. If modulation
|
395
395
|
does not find the module specified by the given relative path, it will attempt
|
396
|
-
to load a gem by the same name.
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
396
|
+
to load a gem by the same name. It is also possible to load specific files
|
397
|
+
inside modules by specifying a sub-path:
|
398
|
+
|
399
|
+
```ruby
|
400
|
+
require 'modulation'
|
401
|
+
MyFeature = import 'my_gem/my_feature'
|
402
|
+
```
|
403
|
+
|
404
|
+
> **Note**: Since there's not much of a point in `import`ing gems that do not use
|
405
|
+
> Modulation to export symbols, Modulation will refuse to import any gem that
|
406
|
+
> does not depend on Modulation.
|
404
407
|
|
405
408
|
## Coding style recommendations
|
406
409
|
|
data/lib/modulation.rb
CHANGED
data/lib/modulation/core.rb
CHANGED
@@ -26,14 +26,27 @@ module Modulation
|
|
26
26
|
@full_backtrace = true
|
27
27
|
end
|
28
28
|
|
29
|
+
GEM_REQUIRE_ERROR_MESSAGE = <<~EOF
|
30
|
+
Can't import from a gem that doesn't depend on Modulation. Please use `require` instead of `import`.
|
31
|
+
EOF
|
32
|
+
|
29
33
|
# Imports a module from a file
|
30
34
|
# If the module is already loaded, returns the loaded module.
|
31
35
|
# @param path [String] unqualified file name
|
32
36
|
# @param caller_location [String] caller location
|
33
37
|
# @return [Module] loaded module object
|
34
38
|
def import(path, caller_location = caller(1..1).first)
|
35
|
-
|
36
|
-
|
39
|
+
abs_path = Paths.absolute_path(path, caller_location) ||
|
40
|
+
Paths.lookup_gem_path(path)
|
41
|
+
|
42
|
+
case abs_path
|
43
|
+
when String
|
44
|
+
@loaded_modules[abs_path] || create_module_from_file(abs_path)
|
45
|
+
when :require_gem
|
46
|
+
raise_error(LoadError.new(GEM_REQUIRE_ERROR_MESSAGE), caller)
|
47
|
+
else
|
48
|
+
raise_error(LoadError.new("Module not found: #{path}"), caller)
|
49
|
+
end
|
37
50
|
end
|
38
51
|
|
39
52
|
# Creates a new module from a source file
|
@@ -42,16 +55,21 @@ module Modulation
|
|
42
55
|
def create_module_from_file(path)
|
43
56
|
Builder.make(location: path)
|
44
57
|
rescue StandardError => e
|
45
|
-
|
58
|
+
raise_error(e)
|
46
59
|
end
|
47
60
|
|
48
|
-
# (Re-)raises an error, filtering its backtrace to remove stack
|
49
|
-
# occuring in Modulation code
|
61
|
+
# (Re-)raises an error, potentially filtering its backtrace to remove stack
|
62
|
+
# frames occuring in Modulation code
|
50
63
|
# @param error [Error] raised error
|
64
|
+
# @param caller [Array] error backtrace
|
51
65
|
# @return [void]
|
52
|
-
def
|
53
|
-
|
54
|
-
|
66
|
+
def raise_error(error, caller = error.backtrace)
|
67
|
+
if @full_backtrace
|
68
|
+
error.set_backtrace(caller)
|
69
|
+
else
|
70
|
+
error.set_backtrace(caller.reject { |l| l =~ /^#{Modulation::DIR}/ })
|
71
|
+
end
|
72
|
+
raise error
|
55
73
|
end
|
56
74
|
|
57
75
|
# Reloads the given module from its source file
|
@@ -70,7 +88,7 @@ module Modulation
|
|
70
88
|
mod.tap { Builder.set_exported_symbols(mod, mod.__exported_symbols, true) }
|
71
89
|
end
|
72
90
|
|
73
|
-
# Maps the given path to the given mock module, restoring the previously
|
91
|
+
# Maps the given path to the given mock module, restoring the previously
|
74
92
|
# loaded module (if any) after calling the given block
|
75
93
|
# @param path [String] module path
|
76
94
|
# @param mod [Module] module
|
data/lib/modulation/paths.rb
CHANGED
@@ -13,14 +13,12 @@ module Modulation
|
|
13
13
|
# @param path [String] unqualified file name
|
14
14
|
# @param caller_location [String] caller location
|
15
15
|
# @return [String] absolute file name
|
16
|
-
def absolute_path(path, caller_location
|
17
|
-
orig_path = path
|
16
|
+
def absolute_path(path, caller_location)
|
18
17
|
caller_file = caller_location[CALLER_FILE_REGEXP, 1]
|
19
|
-
|
18
|
+
return nil unless caller_file
|
20
19
|
|
21
20
|
path = File.expand_path(path, File.dirname(caller_file))
|
22
|
-
check_path(path)
|
23
|
-
(raise "Module not found: #{path}")
|
21
|
+
check_path(path)
|
24
22
|
end
|
25
23
|
|
26
24
|
# Checks that the given path references an existing file, adding the .rb
|
@@ -35,19 +33,44 @@ module Modulation
|
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
38
|
-
|
39
|
-
|
36
|
+
GEM_NAME_RE = /^([^\/]+)/
|
37
|
+
|
38
|
+
# Resolves the provided path by looking for a corresponding gem. If no gem
|
39
|
+
# is found, returns nil. If the corresponding gem does not use modulation,
|
40
|
+
# returns :require_gem, which signals that the gem must be required.
|
40
41
|
# @param name [String] gem name
|
41
|
-
# @return [String] absolute path
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
# @return [String, Symbol] absolute path or :require_gem
|
43
|
+
def lookup_gem_path(name)
|
44
|
+
gem = name[GEM_NAME_RE, 1] || name
|
45
|
+
spec = Gem::Specification.find_by_name(gem)
|
46
|
+
|
47
|
+
if gem_uses_modulation?(spec)
|
48
|
+
find_gem_based_path(spec, name)
|
49
|
+
else
|
50
|
+
:require_gem
|
46
51
|
end
|
47
|
-
path = File.join(spec.full_require_paths, "#{name}.rb")
|
48
|
-
File.file?(path) ? path : nil
|
49
52
|
rescue Gem::MissingSpecError
|
50
53
|
nil
|
51
54
|
end
|
55
|
+
|
56
|
+
# Returns true if given gemspec depends on modulation, which means it can
|
57
|
+
# be loaded using `import`
|
58
|
+
# @param gemspec [Gem::Specification] gem spec
|
59
|
+
# @return [Boolean] does gem depend on modulation?
|
60
|
+
def gem_uses_modulation?(gemspec)
|
61
|
+
gemspec.dependencies.map(&:name).include?('modulation')
|
62
|
+
end
|
63
|
+
|
64
|
+
# Finds full path for gem file based on gem's require paths
|
65
|
+
# @param gemspec [Gem::Specification] gem spec
|
66
|
+
# @param path [String] given import path
|
67
|
+
# @return [String] full path
|
68
|
+
def find_gem_based_path(gemspec, path)
|
69
|
+
gemspec.full_require_paths.each do |p|
|
70
|
+
full_path = check_path(File.join(p, path))
|
71
|
+
return full_path if full_path
|
72
|
+
end
|
73
|
+
nil
|
74
|
+
end
|
52
75
|
end
|
53
76
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: modulation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.12'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
@@ -9,7 +9,35 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2018-08-20 00:00:00.000000000 Z
|
12
|
-
dependencies:
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.11.3
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.11.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: redis
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.0.1
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.0.1
|
13
41
|
description: "Modulation provides an better way to organize Ruby code. Modulation
|
14
42
|
lets you \nexplicitly import and export declarations in order to better control
|
15
43
|
\ndependencies in your codebase. Modulation helps you refrain from littering\nthe
|
@@ -19,7 +47,9 @@ executables: []
|
|
19
47
|
extensions: []
|
20
48
|
extra_rdoc_files:
|
21
49
|
- README.md
|
50
|
+
- CHANGELOG.md
|
22
51
|
files:
|
52
|
+
- CHANGELOG.md
|
23
53
|
- README.md
|
24
54
|
- lib/modulation.rb
|
25
55
|
- lib/modulation/builder.rb
|