malachite 1.1.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0ba4057a948f808a684ea7dd503ccaabe46bbba5
4
- data.tar.gz: 8d2b9b35cd4104cd735e0c92db2c7098b98b30f4
2
+ SHA256:
3
+ metadata.gz: d03c3c2f8c6c1f7f95459b33f9b1fc1de9059f9450979220d8078e323c6d7f59
4
+ data.tar.gz: d5fd7eebc38c4dd8ece734a2e763998e5c8fc110ea839254608b949c3304a53a
5
5
  SHA512:
6
- metadata.gz: ec0603aa1eac3c6d5428c2b321ef4cb6a5a97f7aa91e36d356872f37419afec30e6a2f806e89ce8eac3e362ac9da93d61a021c93dfdfd7804bb859d9dd787631
7
- data.tar.gz: d923d46e0ab54ff1c0d687a24a7019c715cf08b93d5fe5f7df08621f095f616308393e8a3e9d1525390f93bfc49532e95faea3b0822483b813e769c6aab03f89
6
+ metadata.gz: da6e655906d4dc4e6460747a2fda0f251f11d8b905a4ce00ad781d25813ce39e82893cc91c2f13ff2103f849ebc87840de13a19f84ef70329554b2055475e6da
7
+ data.tar.gz: 156e3a2c07a8270cd0cb09343885cc590887b8962a9cc0d107ba1e19c8b5b196d7dbe13983917a43aae0b2b4453bd16748919f509bd5e0426653314467c3ff51
@@ -1 +1 @@
1
- 2.3.3
1
+ 2.6.3
data/Gemfile CHANGED
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
  gemspec
data/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Call Go functions directly from Rails.
4
4
 
5
+
5
6
  ### Requirements
6
7
 
7
- Requires Ruby >= 2.0.0, Go 1.5 <-> 1.11.
8
+ Requires Ruby >= 2.0.0, Go 1.5+.
8
9
 
9
- Xcode 8.3 is broken, do not use until [this is fixed](https://github.com/golang/go/issues/19734)
10
10
 
11
11
  ### Installation
12
12
 
@@ -54,6 +54,7 @@ More examples can be found in [examples](https://github.com/zhubert/malachite/wi
54
54
 
55
55
  Note: This would actually be slower than doing it in Ruby, due to the JSON serialization.
56
56
 
57
+
57
58
  ### Testing
58
59
 
59
60
  Check out the wiki on [Testing](https://github.com/zhubert/malachite/wiki/Testing)
@@ -62,22 +63,13 @@ Check out the wiki on [Testing](https://github.com/zhubert/malachite/wiki/Testin
62
63
 
63
64
  Code generation.
64
65
 
65
- * The first time the function is called, Malachite will build a shared library from all the Go code in your ```app/go``` folder
66
+ * On every load in development and one time on boot elsewhere, Malachite will build a shared library from all the Go code in your ```app/go``` folder
66
67
  * It then uses Ruby's Fiddle to call the shared library
67
68
  * Arguments are passed back and forth via JSON
68
69
 
69
70
  Because of the JSON step, you'll only see real performance gains on computationally difficult tasks. Ruby's JSON conversion is a large tax.
70
71
 
71
- Note: You can also request precompilation. This is helpful for production environments. In an initializer:
72
-
73
- ```ruby
74
- Malachite.precompile
75
- ```
76
72
 
77
73
  ### Ruby 2.2.4+
78
74
 
79
75
  It's strongly recommended to use the [newest release of Ruby](https://www.ruby-lang.org/en/news/2015/12/16/unsafe-tainted-string-usage-in-fiddle-and-dl-cve-2015-7551/) as there was a security issue with older versions of Fiddle.
80
-
81
- ### Production Readiness
82
-
83
- Likely more gotchas with architecture variations and Cgo. Submit a PR if you find something.
data/Rakefile CHANGED
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rake/testtask'
5
+
3
6
  Rake::TestTask.new do |t|
4
7
  t.libs << 'test'
5
8
  t.pattern = 'test/*_test.rb'
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'malachite/version'
2
- fail "Malachite #{Malachite::VERSION} does not support Ruby < 2.0.0" if RUBY_VERSION < '2.0.0'
4
+ raise "Malachite #{Malachite::VERSION} does not support Ruby < 2.0.0" if RUBY_VERSION < '2.0.0'
3
5
 
4
6
  require 'json'
5
7
  require 'fiddle'
@@ -13,26 +15,6 @@ require 'malachite/file_compiler'
13
15
  require 'malachite/compiler'
14
16
 
15
17
  module Malachite
16
- DEFAULTS = {
17
- precompile: false
18
- }
19
-
20
- def self.options
21
- @options ||= DEFAULTS.dup
22
- end
23
-
24
- def self.options=(opts)
25
- @options = opts
26
- end
27
-
28
- def self.precompile?
29
- Malachite.options.fetch(:precompile, false)
30
- end
31
-
32
- def self.precompile
33
- Malachite.options[:precompile] = true
34
- end
35
-
36
18
  def self.method_missing(name, args)
37
19
  Malachite::Client.new(name, args).call
38
20
  end
@@ -46,8 +28,4 @@ module Malachite
46
28
  end
47
29
  end
48
30
 
49
- if defined?(::Rails::Engine)
50
- require 'malachite/railtie'
51
- else
52
- fail "Malachite #{Malachite::VERSION} requires Rails"
53
- end
31
+ require 'malachite/railtie' if defined?(Rails)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Malachite
2
4
  class Client
3
5
  def initialize(name, args)
@@ -1,3 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'English'
4
+ require 'open3'
5
+
1
6
  module Malachite
2
7
  class Compiler
3
8
  def initialize
@@ -7,6 +12,7 @@ module Malachite
7
12
 
8
13
  def compile
9
14
  return @compiled_file if File.exist?(@compiled_file) && File.exist?(@compiled_header)
15
+
10
16
  compile!
11
17
  end
12
18
 
@@ -15,21 +21,12 @@ module Malachite
15
21
  def compile!
16
22
  modify_source_files_in_tmp
17
23
 
18
- if modified_go_files == []
19
- raise Malachite::BuildError, 'Nothing to build, there are no Go files in tmp'
20
- end
21
-
22
- unless system({ 'CGO_ENABLED' => '1' }, 'go', 'build', '-buildmode=c-shared', '-o', @compiled_file, *modified_go_files)
23
- raise Malachite::BuildError, 'Unable to Build Shared Library, is Go 1.5+ installed?'
24
- end
24
+ raise Malachite::BuildError, 'Nothing to build, there are no Go files in tmp' if modified_go_files == []
25
25
 
26
- unless File.exist?(@compiled_header)
27
- raise Malachite::BuildError, 'Unable to Build Header File'
28
- end
29
-
30
- unless File.exist?(@compiled_file)
31
- raise Malachite::BuildError, 'Unable to Build Shared Object'
32
- end
26
+ stdout, stderr, status = Open3.capture3({ 'CGO_ENABLED' => '1' }, 'go', 'build', '-buildmode=c-shared', '-o', @compiled_file, *modified_go_files)
27
+ raise Malachite::BuildError, "Unable to Build Shared Library: #{stdout} #{stderr}" unless status.success?
28
+ raise Malachite::BuildError, 'Unable to Build Header File' unless File.exist?(@compiled_header)
29
+ raise Malachite::BuildError, 'Unable to Build Shared Object' unless File.exist?(@compiled_file)
33
30
 
34
31
  path_to_compiled_file
35
32
  end
@@ -38,6 +35,7 @@ module Malachite
38
35
  source_files.each do |f|
39
36
  Malachite::FileCompiler.new(f).compile
40
37
  end
38
+
41
39
  File.open(Rails.root.join('tmp', 'main.go').to_s, 'w') do |file|
42
40
  file.puts main_boilerplate
43
41
  file.close
@@ -53,7 +51,7 @@ module Malachite
53
51
  end
54
52
 
55
53
  def main_boilerplate
56
- File.read(File.expand_path('../main.go.tmpl', __FILE__))
54
+ File.read(File.expand_path('main.go.tmpl', __dir__))
57
55
  end
58
56
 
59
57
  def path_to_compiled_file
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Malachite
2
4
  class BuildError < StandardError; end
3
5
  class ArgumentError < StandardError; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Malachite
2
4
  class FileCompiler
3
5
  def initialize(file)
@@ -20,22 +22,22 @@ module Malachite
20
22
  private
21
23
 
22
24
  def cgo_tmpl
23
- cgo = File.read(File.expand_path('../cgo.tmpl', __FILE__))
24
- return cgo.gsub(/HEADER/, RbConfig::CONFIG['rubyhdrdir']).gsub(/ARCH/, RbConfig::CONFIG['rubyarchhdrdir'])
25
+ cgo = File.read(File.expand_path('cgo.tmpl', __dir__))
26
+ cgo.gsub(/HEADER/, RbConfig::CONFIG['rubyhdrdir']).gsub(/ARCH/, RbConfig::CONFIG['rubyarchhdrdir'])
25
27
  end
26
28
 
27
- def source_file(f)
28
- File.readlines(f).drop(1)
29
+ def source_file(file)
30
+ File.readlines(file).drop(1)
29
31
  end
30
32
 
31
33
  def exporter_boilerplate(file)
32
- exporter = File.read(File.expand_path('../exporter.go.tmpl', __FILE__))
34
+ exporter = File.read(File.expand_path('exporter.go.tmpl', __dir__))
33
35
  method_name, method_type = extract_method_and_type(file)
34
- return exporter.gsub(/YYYYYY/, "#{method_type}{}").gsub(/XXXXXX/, method_name)
36
+ exporter.gsub(/YYYYYY/, "#{method_type}{}").gsub(/XXXXXX/, method_name)
35
37
  end
36
38
 
37
- def file_has_handle_function?(f)
38
- source = File.read(f)
39
+ def file_has_handle_function?(file)
40
+ source = File.read(file)
39
41
  match = /^func Handle(.*?)\(\w+ (.*?)\)/.match(source)
40
42
  match != nil
41
43
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fiddle'
2
4
 
3
5
  module Malachite
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Malachite
2
4
  def self.function_cache
3
5
  @function_cache ||= {}
@@ -9,7 +11,8 @@ module Malachite
9
11
 
10
12
  def self.from_function_cache(method_name)
11
13
  existing_function = Malachite.function_cache[method_name]
12
- return existing_function if existing_function != nil
14
+ return existing_function unless existing_function.nil?
15
+
13
16
  Malachite.add_to_function_cache(method_name)
14
17
  end
15
18
 
@@ -37,6 +40,6 @@ module Malachite
37
40
  end
38
41
 
39
42
  def self.shared_object_path
40
- @so_path ||= Malachite::Compiler.new.compile
43
+ @shared_object_path ||= Malachite::Compiler.new.compile
41
44
  end
42
45
  end
@@ -1,22 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Malachite
2
- def self.hook_rails!
3
- Dir.glob(Rails.root.join('tmp', '*.so')).each do |file|
4
+ def self.setup!
5
+ Dir.glob(Rails.root.join('tmp', '*.{so,go,h}')).each do |file|
4
6
  File.delete(file)
5
7
  end
6
- Dir.glob(Rails.root.join('tmp', '*.go')).each do |file|
7
- File.delete(file)
8
- end
9
- Dir.glob(Rails.root.join('tmp', '*.h')).each do |file|
10
- File.delete(file)
11
- end
12
- Malachite::Compiler.new.compile if Malachite.precompile?
8
+
9
+ Malachite::Compiler.new.compile
13
10
  end
14
- class MalachiteRailtie < Rails::Railtie
11
+
12
+ class Railtie < Rails::Railtie
15
13
  rake_tasks do
16
14
  load 'malachite/tasks/malachite.rake'
17
15
  end
18
- initializer 'malachite.configure_rails_initialization' do
19
- Malachite.hook_rails!
16
+
17
+ # Executed once in production/staging and before each request in development.
18
+ config.to_prepare do
19
+ Malachite.setup!
20
20
  end
21
21
  end
22
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].each do |task|
2
4
  load task
3
5
  end
@@ -4,4 +4,18 @@ namespace :malachite do
4
4
  test_files = Dir["#{Rails.root.join('app', 'go')}/**/*.go"]
5
5
  system({ 'CGO_ENABLED' => '1' }, 'go', 'test', *test_files)
6
6
  end
7
+
8
+ desc 'deletes any existing shared library and re-compiles'
9
+ task :compile do
10
+ Dir.glob(Rails.root.join('tmp', '*.so')).each do |file|
11
+ File.delete(file)
12
+ end
13
+ Dir.glob(Rails.root.join('tmp', '*.go')).each do |file|
14
+ File.delete(file)
15
+ end
16
+ Dir.glob(Rails.root.join('tmp', '*.h')).each do |file|
17
+ File.delete(file)
18
+ end
19
+ Malachite::Compiler.new.compile
20
+ end
7
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Malachite
2
- VERSION = '1.1.0'
4
+ VERSION = '1.2.0'
3
5
  end
@@ -16,7 +16,8 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.required_ruby_version = '>= 2.0.0'
18
18
  spec.add_dependency 'activesupport'
19
- spec.add_development_dependency 'bundler', '~> 1.9'
19
+ spec.add_development_dependency 'bundler', '~> 2.1'
20
+ spec.add_development_dependency 'rubocop'
20
21
  spec.add_development_dependency 'rake', '~> 10.0'
21
22
  spec.add_development_dependency 'minitest', '~> 5'
22
23
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class ClientTest < MiniTest::Test
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class FileCompilerTest < MiniTest::Test
@@ -7,7 +9,7 @@ class FileCompilerTest < MiniTest::Test
7
9
 
8
10
  def test_confirm_compilation_matches_fixture
9
11
  compiled = File.read(Rails.root.join('tmp', 'upcase.go')).to_s
10
- valid = File.read(File.expand_path('../fixtures/valid_upcase.go', __FILE__)).gsub(/HEADER/, RbConfig::CONFIG['rubyhdrdir']).gsub(/ARCH/, RbConfig::CONFIG['rubyarchhdrdir'])
12
+ valid = File.read(File.expand_path('fixtures/valid_upcase.go', __dir__)).gsub(/HEADER/, RbConfig::CONFIG['rubyhdrdir']).gsub(/ARCH/, RbConfig::CONFIG['rubyarchhdrdir'])
11
13
  assert_equal compiled, valid
12
14
  end
13
15
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  # Not really a performance test, but designed to generate more work
@@ -1,12 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
4
+ require 'ostruct'
5
+
2
6
  module Rails
3
- Engine = {}
7
+ Engine = {}.freeze
8
+
4
9
  def self.root
5
10
  Pathname.new(File.join(Dir.pwd, 'test', 'dummy'))
6
11
  end
12
+
7
13
  class Railtie
8
14
  def self.rake_tasks; end
9
15
 
16
+ def self.config
17
+ OpenStruct.new(to_prepare: {})
18
+ end
19
+
10
20
  def self.initializer(_); end
11
21
  end
12
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails_stub'
2
4
  require 'malachite'
3
5
  require 'minitest/autorun'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: malachite
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zack Hubert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-01 00:00:00.000000000 Z
11
+ date: 2020-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -30,14 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.9'
33
+ version: '2.1'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.9'
40
+ version: '2.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -119,8 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
133
  - !ruby/object:Gem::Version
120
134
  version: '0'
121
135
  requirements: []
122
- rubyforge_project:
123
- rubygems_version: 2.5.2
136
+ rubygems_version: 3.0.3
124
137
  signing_key:
125
138
  specification_version: 4
126
139
  summary: A RubyGem which enables calling Go code from Rails