modulation 0.34 → 1.0

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: 1b35f333f45c8017d3fd44700fc5cd3d16dcdd575be012b3f86f2af17c2fcaef
4
- data.tar.gz: de1b7cf9b6cd1d39080fd2ef971d99b23fa2b91f18a90db2bbcacf9debfdd7c7
3
+ metadata.gz: a81a52fa3760bfbda94193a1e1de70bd498dd8112455ec774fc9b5735bf8fbfa
4
+ data.tar.gz: 37e1ca88843461ccc8e3d137e4c686d3969641a381210ec7cb40a0215ec184c4
5
5
  SHA512:
6
- metadata.gz: 914789190308c5b9133d4bc3f2a5b6209fe9123ba1d984e7e77b1062f6392b9cb09a4db32b44b631db631080e655bf7dfb32b1955693eb39d0573a85487dba4d
7
- data.tar.gz: 2cba7fed4ae3c0a36abb3f8a2f1505074191ba52cfa7510022060730accf39a932e00b6e3323e7b0643ac8e6932f6046be4e10fa7bff435004a6ceb75492bd68
6
+ metadata.gz: 2f57985001fea20c87d1b8a7a1e06244fd21a52a5e1830177ee3d379e9cb81913a03dde161fdcc78fe4d7f14d8a486def00058cca2b01b8f8e233cb70b413107
7
+ data.tar.gz: 0cbc73dc2b7684a7b63fe50c6d505175f78b894fa0b043991ae4591cfc38e1a3849c3ac6c4b7f50e1cdb190f8570e6e00cd4405cb3f95d9494aff7485cf64437
@@ -1,8 +1,13 @@
1
+ 1.0 2019-10-18
2
+ --------------
3
+
4
+ * Cleanup code
5
+ * Obfuscate bootstrap dictionary code in packages
6
+ * Move packer, bootstrap, CLI, creator code into stock modules
7
+
1
8
  0.34 2019-10-14
2
9
  ---------------
3
10
 
4
- * Obfuscate bootstrapping code in packages
5
- * Move packer, bootstrap, CLI, creator code into stock modules
6
11
  * Improve README
7
12
 
8
13
  0.33 2019-10-02
data/README.md CHANGED
@@ -34,11 +34,13 @@ a functional style, minimizing boilerplate code.
34
34
  [importing](#importing-declarations) of methods and constants** lets you
35
35
  control the public interface for each module, as well as keep track of all
36
36
  dependencies in your code.
37
+ - **[Tagged paths](#using-tags-to-designate-common-subdirectories)** simplify
38
+ the management of dependencies in large applications.
37
39
  - **[Lazy Loading](#lazy-loading)** improves start up time and memory
38
40
  consumption.
39
41
  - **[Hot module reloading](#reloading-modules)** streamlines your development
40
42
  process.
41
- - **[Dependency mocking](#mocking-dependencies)** facilitates testing.
43
+ - **[Module mocking](#mocking-modules)** facilitates testing.
42
44
  - **[Dependency introspection](#dependency-introspection)** lets you introspect
43
45
  your dependencies at runtime.
44
46
  - **[Application packing](#packing-applications-with-modulation)** lets you
@@ -472,7 +474,7 @@ class FibTest < Minitest::Test
472
474
  end
473
475
  ```
474
476
 
475
- ### Mocking dependencies
477
+ ### Mocking modules
476
478
 
477
479
  Modules loaded by Modulation can be easily mocked when running tests or specs,
478
480
  using `Modulation.mock`:
@@ -503,6 +505,9 @@ class UserControllerTest < Minitest::Test
503
505
  end
504
506
  ```
505
507
 
508
+ `Modulation.mock` accepts a module path and a receiver, and the module stays
509
+ mocked within the given block.
510
+
506
511
  ### Lazy Loading
507
512
 
508
513
  Modulation allows the use of lazy-loaded modules - loading of modules only once
@@ -583,6 +588,30 @@ settings = import('settings')
583
588
  settings = settings.__reload!
584
589
  ```
585
590
 
591
+ Please note that Modulation does not include a directory watcher that
592
+ automatically reloads changed modules. This is due to multiple considerations
593
+ that include the chosen threading model, or the reactor engine in use, or even
594
+ the chosen solution for watching files (whether it's an external gem or an
595
+ internal tool).
596
+
597
+ It is, however, quite trivial to watch files using
598
+ [`directory_watcher`](https://rubygems.org/gems/directory_watcher/):
599
+
600
+ ```ruby
601
+ require 'directory_watcher'
602
+
603
+ dw = DirectoryWatcher.new 'lib', glob: '**/*.rb', interval: 2, pre_load: true
604
+ dw.add_observer do |*events|
605
+ events.each do |e|
606
+ next unless e.type == :modified
607
+
608
+ Modulation.reload e.path
609
+ end
610
+ end
611
+
612
+ dw.start
613
+ ```
614
+
586
615
  ### Retaining state between reloads
587
616
 
588
617
  Before a module is reloaded, all of its methods and constants are removed. In
@@ -780,41 +809,52 @@ end
780
809
 
781
810
  ## API Reference
782
811
 
783
- This section will be expanded on in a future release.
812
+ ### Kernel
784
813
 
785
- #### `__module_info`
814
+ #### `Kernel#auto_import_map(path, options = {})`
786
815
 
787
- ### `__reload!`
816
+ Returns a hash mapping keys to corresponding module files inside the given
817
+ directory path. Modules are loaded automatically upon accessing hash keys.
788
818
 
789
- #### `alias_method_once()`
819
+ #### `Kernel#import(path)`
790
820
 
791
- #### `auto_import()`
821
+ #### `Kernel#import_all(path)`
792
822
 
793
- #### `auto_import_map()`
823
+ #### `Kernel#import_map(path, options = {})`
794
824
 
795
- #### `export()`
825
+ ### Module
796
826
 
797
- #### `export_default()`
827
+ #### `Module#__module_info`
798
828
 
799
- #### `export_from_receiver()`
829
+ Returns a hash containing information about the module. This currently includes
830
+ the following entries:
800
831
 
801
- #### `extend_from()`
832
+ location|Absolute module file path
833
+ exported_symbols|Array containing all symbols exported by the module
802
834
 
803
- #### `import()`
835
+ ### `Module#__reload!`
804
836
 
805
- #### `import_all()`
837
+ #### `Module#alias_method_once(new_name, old_name)`
806
838
 
807
- #### `import_map()`
839
+ #### `Module#auto_import(sym, path)`
808
840
 
809
- #### `include_from()`
841
+ #### `Module#export(*symbols)`
810
842
 
811
- #### `Modulation.full_backtrace!`
843
+ #### `Module#export_default(value)`
844
+
845
+ #### `Module#export_from_receiver(receiver)`
812
846
 
813
- #### `Modulation.reload()`
847
+ #### `Module#extend_from(path)`
814
848
 
815
- #### `MODULE`
849
+ #### `Module#include_from(path, *symbols)`
850
+
851
+ #### `Module::MODULE`
852
+
853
+ ### Modulation
854
+
855
+ #### `Modulation.full_backtrace!`
816
856
 
817
- #### `MODULE.__module_info`
857
+ #### `Modulation.reload`
818
858
 
819
859
  ## Why you should not use Modulation
820
860
 
@@ -31,8 +31,8 @@ module Modulation
31
31
 
32
32
  @__export_directives ||= []
33
33
  @__export_directives << {
34
- method: :export,
35
- args: symbols,
34
+ method: :export,
35
+ args: symbols,
36
36
  export_caller: caller
37
37
  }
38
38
  end
@@ -46,8 +46,8 @@ module Modulation
46
46
 
47
47
  @__export_directives ||= []
48
48
  @__export_directives << {
49
- method: :export_from_receiver,
50
- args: name,
49
+ method: :export_from_receiver,
50
+ args: name,
51
51
  export_caller: caller
52
52
  }
53
53
  end
@@ -113,7 +113,7 @@ module Modulation
113
113
 
114
114
  def __traverse_dependencies(&block)
115
115
  __dependencies.each do |mod|
116
- block.call mod
116
+ block.(mod)
117
117
  if mod.respond_to?(:__traverse_dependencies)
118
118
  mod.__traverse_dependencies(&block)
119
119
  end
@@ -27,9 +27,8 @@ def patch_builder
27
27
  end
28
28
 
29
29
  def transform_module_info(info)
30
- if find(info[:location])
31
- info[:source] = read_file(info[:location])
32
- end
30
+ location = info[:location]
31
+ info[:source] = read_file(location) if location
33
32
  info
34
33
  end
35
34
 
@@ -46,4 +45,4 @@ def read_file(path)
46
45
  (offset, length) = @dictionary[path]
47
46
  @data.seek(@data_offset + offset)
48
47
  Zlib::Inflate.inflate(@data.read(length))
49
- end
48
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  export_default :CLI
4
4
 
5
+ # Command line interface functionality
5
6
  class CLI
6
7
  def initialize(argv)
7
8
  @argv = argv
@@ -25,15 +26,15 @@ class CLI
25
26
  cleanup_backtrace(e)
26
27
  raise e
27
28
  end
28
-
29
+
29
30
  def run_file(arg)
30
31
  fn, method = filename_and_method_from_arg(arg)
31
32
  mod = import(File.expand_path(fn))
32
33
  mod.send(method) if method
33
34
  end
34
-
35
+
35
36
  FILENAME_AND_METHOD_RE = /^([^\:]+)\:(.+)$/.freeze
36
-
37
+
37
38
  def filename_and_method_from_arg(arg)
38
39
  if arg =~ FILENAME_AND_METHOD_RE
39
40
  match = Regexp.last_match
@@ -42,14 +43,14 @@ class CLI
42
43
  [arg, :main]
43
44
  end
44
45
  end
45
-
46
+
46
47
  BACKTRACE_RE = /^(#{Modulation::DIR})|(bin\/mdl)/.freeze
47
-
48
+
48
49
  def cleanup_backtrace(error)
49
50
  backtrace = error.backtrace.reject { |l| l =~ BACKTRACE_RE }
50
51
  error.set_backtrace(backtrace)
51
52
  end
52
-
53
+
53
54
  def collect_deps(path, array)
54
55
  if File.directory?(path)
55
56
  Dir["#{path}/**/*.rb"].each { |fn| collect_deps(fn, array) }
@@ -61,17 +62,17 @@ class CLI
61
62
  end
62
63
  end
63
64
  end
64
-
65
+
65
66
  def deps
66
67
  paths = []
67
68
  @argv.each { |arg| collect_deps(arg, paths) }
68
69
  puts(*paths)
69
70
  end
70
-
71
+
71
72
  def pack
72
73
  STDOUT << import('@modulation/packer').pack(@argv, hide_filenames: true)
73
74
  end
74
-
75
+
75
76
  def version
76
77
  puts "Modulation version #{Modulation::VERSION}"
77
78
  end
@@ -4,7 +4,7 @@ export :from_block,
4
4
  :from_hash,
5
5
  :from_string
6
6
 
7
- RE_ATTR = /^@(.+)$/.freeze
7
+ RE_ATTR = /^@(.+)$/.freeze
8
8
 
9
9
  def from_block(block)
10
10
  Module.new.tap { |m| m.instance_eval(&block) }
@@ -16,20 +16,22 @@ end
16
16
  def from_hash(hash)
17
17
  Module.new.tap do |m|
18
18
  s = m.singleton_class
19
- hash.each do |k, v|
20
- if k =~ Modulation::RE_CONST
21
- m.const_set(k, v)
22
- elsif k =~ RE_ATTR
23
- m.instance_variable_set(k, v)
24
- elsif v.respond_to?(:to_proc)
25
- s.send(:define_method, k) { |*args| instance_exec(*args, &v) }
26
- else
27
- s.send(:define_method, k) { v }
28
- end
29
- end
19
+ hash.each { |k, v| process_hash_entry(k, v, m, s) }
20
+ end
21
+ end
22
+
23
+ def process_hash_entry(key, value, mod, singleton)
24
+ if key =~ Modulation::RE_CONST
25
+ mod.const_set(key, value)
26
+ elsif key =~ RE_ATTR
27
+ mod.instance_variable_set(key, value)
28
+ elsif value.respond_to?(:to_proc)
29
+ singleton.send(:define_method, key) { |*args| instance_exec(*args, &value) }
30
+ else
31
+ singleton.send(:define_method, key) { value }
30
32
  end
31
33
  end
32
34
 
33
35
  def from_string(str)
34
- m = Modulation::Builder.make(source: str)
36
+ Modulation::Builder.make(source: str)
35
37
  end
@@ -44,29 +44,27 @@ def generate_packed_data(deps, entry_point_filename)
44
44
  end
45
45
 
46
46
  def pack_files(files, entry_point_filename)
47
+ dictionary = { entry_point: entry_point_filename }
47
48
  data = (+'').encode('ASCII-8BIT')
48
49
  last_offset = 0
49
- dictionary = {
50
- entry_point: entry_point_filename
51
- }
52
50
  files.each_with_object(dictionary) do |(path, content), dict|
53
- zipped = Zlib::Deflate.deflate(content)
54
- size = zipped.bytesize
55
-
56
- data << zipped
57
- dict[path] = [last_offset, size]
58
- last_offset += size
51
+ last_offset = add_packed_file(path, content, data, dict, last_offset)
59
52
  end
60
- packed_dictionary = Zlib::Deflate.deflate(dictionary.inspect)
61
- data << packed_dictionary
53
+ data << Zlib::Deflate.deflate(dictionary.inspect)
54
+
55
+ { dict_offset: last_offset, data: data }
56
+ end
57
+
58
+ def add_packed_file(path, content, data, dict, last_offset)
59
+ zipped = Zlib::Deflate.deflate(content)
60
+ size = zipped.bytesize
62
61
 
63
- {
64
- dict_offset: last_offset,
65
- data: data
66
- }
62
+ data << zipped
63
+ dict[path] = [last_offset, size]
64
+ last_offset + size
67
65
  end
68
66
 
69
- def generate_bootstrap(package_info, entry_point)
67
+ def generate_bootstrap(package_info, _entry_point)
70
68
  format(
71
69
  bootstrap_template,
72
70
  modulation_version: Modulation::VERSION,
@@ -16,10 +16,14 @@ module Modulation
16
16
 
17
17
  def tags
18
18
  @tags ||= {
19
- 'modulation' => File.join(Modulation::DIR, 'modulation/modules')
19
+ 'modulation' => modules_path
20
20
  }
21
21
  end
22
22
 
23
+ def modules_path
24
+ File.join(Modulation::DIR, 'modulation/modules')
25
+ end
26
+
23
27
  def add_tags(new_tags, caller_location)
24
28
  caller_file = caller_location[CALLER_FILE_REGEXP, 1]
25
29
  caller_dir = caller_file ? File.dirname(caller_file) : nil
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Modulation
4
- VERSION = '0.34'
4
+ VERSION = '1.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: modulation
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.34'
4
+ version: '1.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-14 00:00:00.000000000 Z
11
+ date: 2019-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest