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