drain 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +6 -2
  3. data/.travis.yml +10 -0
  4. data/.yardopts +6 -1
  5. data/Gemfile +7 -0
  6. data/LICENSE.txt +1 -1
  7. data/README.md +11 -5
  8. data/Rakefile +7 -12
  9. data/drain.gemspec +15 -5
  10. data/gemspec.yml +4 -3
  11. data/lib/dr.rb +1 -0
  12. data/lib/{drain → dr}/base.rb +0 -0
  13. data/lib/{drain → dr}/base/bool.rb +0 -0
  14. data/lib/dr/base/converter.rb +33 -0
  15. data/lib/{drain → dr}/base/encoding.rb +0 -0
  16. data/lib/dr/base/eruby.rb +284 -0
  17. data/lib/{drain → dr}/base/functional.rb +2 -2
  18. data/lib/dr/base/graph.rb +378 -0
  19. data/lib/dr/base/utils.rb +28 -0
  20. data/lib/dr/parse.rb +1 -0
  21. data/lib/dr/parse/simple_parser.rb +70 -0
  22. data/lib/{drain → dr}/parse/time_parse.rb +0 -0
  23. data/lib/dr/ruby_ext.rb +1 -0
  24. data/lib/dr/ruby_ext/core_ext.rb +7 -0
  25. data/lib/{drain/ruby_ext/core_ext.rb → dr/ruby_ext/core_modules.rb} +67 -27
  26. data/lib/{drain → dr}/ruby_ext/meta_ext.rb +57 -30
  27. data/lib/dr/tools.rb +1 -0
  28. data/lib/{drain → dr}/tools/gtk.rb +0 -0
  29. data/lib/dr/version.rb +4 -0
  30. data/lib/drain.rb +2 -1
  31. data/test/helper.rb +12 -1
  32. data/test/test_converter.rb +42 -0
  33. data/test/test_core_ext.rb +116 -0
  34. data/test/test_graph.rb +126 -0
  35. data/test/test_meta.rb +65 -0
  36. data/test/test_simple_parser.rb +41 -0
  37. metadata +45 -21
  38. data/.document +0 -3
  39. data/lib/drain/base/eruby.rb +0 -28
  40. data/lib/drain/base/graph.rb +0 -213
  41. data/lib/drain/parse.rb +0 -5
  42. data/lib/drain/parse/simple_parser.rb +0 -61
  43. data/lib/drain/ruby_ext.rb +0 -5
  44. data/lib/drain/tools.rb +0 -5
  45. data/lib/drain/tools/git.rb +0 -116
  46. data/lib/drain/version.rb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4801bbbd9081149ae66059ccabf69e10a6002c16
4
- data.tar.gz: bd24d077d42a458160c61e985a8f3e2e1d14f323
2
+ SHA256:
3
+ metadata.gz: 2a6165b74687b54296ee9b273eac4465746de73b9774eb5466fd550031897cba
4
+ data.tar.gz: 915728a74d0050b45fec8167e51e2b08c3657defb5fc3187b25b4aca2ff18fb4
5
5
  SHA512:
6
- metadata.gz: f6c18209c458007657d6bc26e79d34f64a50de127c4db0b4d1dd525f3de950eb3d2cf8543a816aaddb4f322fc146e7bde45645f0af0bc95dd01360afe4fd3015
7
- data.tar.gz: 0f64e58698354e4b75385aaa8127eedad9d55d6413fe141f3dea621eeacffb94cc531d3f80ea892ab16465134e28d9879c10884a835f43376de8bc609a615947
6
+ metadata.gz: f1c013bdb8158298fec2a204063d142a328840e9f3bea214036932ddc59f696aca94549190df72b95b3110dbea295f7a2e240bd69dbb3ed7264911a201517297
7
+ data.tar.gz: 4cdffbe87293046d6752bd64a0e7e17224b16786d39cb5ff4f4537a5ed3da6722060acf44475774c4bc788f4b09abbb66cf85833e8027cc990fb79fc862f001c
data/.gitignore CHANGED
@@ -1,2 +1,6 @@
1
- doc/
2
- pkg/
1
+ /.bundle
2
+ /.yardoc/
3
+ /Gemfile.lock
4
+ /doc/
5
+ /pkg/
6
+ /vendor/cache/*.gem
@@ -0,0 +1,10 @@
1
+ ---
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.0
5
+ - 2.3.3
6
+ - 2.2.6
7
+ - 2.1.10
8
+ - ruby-head
9
+ - ruby-head-clang
10
+ script: rake test
data/.yardopts CHANGED
@@ -1 +1,6 @@
1
- --markup markdown -M kramdown --title "drain Documentation" --protected
1
+ --markup markdown
2
+ --title "drain Documentation"
3
+ --protected
4
+ -
5
+ ChangeLog.md
6
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'kramdown'
7
+ end
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015 Damien Robert
1
+ Copyright © 2015–2017 Damien Robert
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,25 +1,31 @@
1
1
  # drain
2
2
 
3
3
  * [Homepage](https://github.com/DamienRobert/drain#readme)
4
- * [Gems]("https://rubygems.org/gems/drain)
5
4
  * [Issues](https://github.com/DamienRobert/drain/issues)
6
- * [Documentation](http://rubydoc.info/gems/drain/frames)
5
+ * [Documentation](http://rubydoc.info/gems/drain)
7
6
  * [Email](mailto:Damien.Olivier.Robert+gems at gmail.com)
8
7
 
8
+ [![Gem Version](https://img.shields.io/gem/v/drain.svg)](https://rubygems.org/gems/drain)
9
+ [![Build Status](https://travis-ci.org/DamienRobert/drain.svg?branch=master)](https://travis-ci.org/DamienRobert/drain)
10
+
9
11
  ## Description
10
12
 
11
13
  Drain is a small set of libraries that I use in my other gems.
12
14
  The Api is far from stable yet, so use at your own risk!
13
15
 
16
+ ## Warning
17
+
18
+ For now the API is experimental and some parts are not ready to use!
19
+
14
20
  ## Install
15
21
 
16
22
  $ gem install drain
17
23
 
18
24
  ## Copyright
19
25
 
20
- Copyright (c) 2015 Damien Robert
26
+ Copyright © 2015–2017 Damien Robert
21
27
 
22
- MIT License. See {file:LICENSE.txt} for details.
28
+ MIT License. See [LICENSE.txt](./LICENSE.txt) for details.
23
29
 
24
30
  Some of the code is inspired by other project, in general I give proper
25
- Acknowledgement in the corresponding file.
31
+ acknowledgement in the corresponding file.
data/Rakefile CHANGED
@@ -1,20 +1,16 @@
1
- # encoding: utf-8
2
-
3
- require 'rubygems'
4
1
  require 'rake'
5
2
 
6
3
  begin
7
- gem 'rubygems-tasks', '~> 0.2'
8
4
  require 'rubygems/tasks'
9
-
10
- Gem::Tasks.new
5
+ Gem::Tasks.new(sign: {checksum: true, pgp: true},
6
+ scm: {status: true}) do |tasks|
7
+ tasks.console.command = 'pry'
8
+ end
11
9
  rescue LoadError => e
12
10
  warn e.message
13
- warn "Run `gem install rubygems-tasks` to install Gem::Tasks."
14
11
  end
15
12
 
16
13
  require 'rake/testtask'
17
-
18
14
  Rake::TestTask.new do |test|
19
15
  test.libs << 'test'
20
16
  test.pattern = 'test/**/test_*.rb'
@@ -22,13 +18,12 @@ Rake::TestTask.new do |test|
22
18
  end
23
19
 
24
20
  begin
25
- gem 'yard', '~> 0.8'
26
21
  require 'yard'
27
-
28
- YARD::Rake::YardocTask.new
22
+ YARD::Rake::YardocTask.new
29
23
  rescue LoadError => e
30
24
  task :yard do
31
- abort "Please run `gem install yard` to install YARD."
25
+ warn e.message
32
26
  end
33
27
  end
34
28
  task :doc => :yard
29
+
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'yaml'
4
2
 
5
3
  Gem::Specification.new do |gem|
@@ -10,8 +8,8 @@ Gem::Specification.new do |gem|
10
8
  lib_dir = File.join(File.dirname(__FILE__),'lib')
11
9
  $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
12
10
 
13
- require 'drain/version'
14
- Drain::VERSION
11
+ require 'dr/version'
12
+ DR::VERSION
15
13
  end
16
14
 
17
15
  gem.summary = gemspec['summary']
@@ -24,6 +22,16 @@ Gem::Specification.new do |gem|
24
22
  glob = lambda { |patterns| gem.files & Dir[*patterns] }
25
23
 
26
24
  gem.files = `git ls-files`.split($/)
25
+
26
+ `git submodule --quiet foreach --recursive pwd`.split($/).each do |submodule|
27
+ submodule.sub!("#{Dir.pwd}/",'')
28
+
29
+ Dir.chdir(submodule) do
30
+ `git ls-files`.split($/).map do |subpath|
31
+ gem.files << File.join(submodule,subpath)
32
+ end
33
+ end
34
+ end
27
35
  gem.files = glob[gemspec['files']] if gemspec['files']
28
36
 
29
37
  gem.executables = gemspec.fetch('executables') do
@@ -38,7 +46,7 @@ Gem::Specification.new do |gem|
38
46
  %w[ext lib].select { |dir| File.directory?(dir) }
39
47
  })
40
48
 
41
- gem.requirements = gemspec['requirements']
49
+ gem.requirements = Array(gemspec['requirements'])
42
50
  gem.required_ruby_version = gemspec['required_ruby_version']
43
51
  gem.required_rubygems_version = gemspec['required_rubygems_version']
44
52
  gem.post_install_message = gemspec['post_install_message']
@@ -56,4 +64,6 @@ Gem::Specification.new do |gem|
56
64
  gem.add_development_dependency(name,split[versions])
57
65
  end
58
66
  end
67
+
68
+ gem.metadata['yard.run']='yri'
59
69
  end
@@ -8,6 +8,7 @@ email: Damien.Olivier.Robert+gems@gmail.com
8
8
  homepage: https://github.com/DamienRobert/drain#readme
9
9
 
10
10
  development_dependencies:
11
- minitest: ~> 5.0
12
- rubygems-tasks: ~> 0.2
13
- yard: ~> 0.8
11
+ minitest: "~> 5.0"
12
+ rake: "~> 10"
13
+ rubygems-tasks: "~> 0.2"
14
+ yard: "~> 0.8"
@@ -0,0 +1 @@
1
+ require 'dr/version'
File without changes
File without changes
@@ -0,0 +1,33 @@
1
+ module DR
2
+ module Converter
3
+ extend self
4
+ #convert an obj to hash, using 'methods' for the methods attributes
5
+ def to_hash(obj=nil, methods:[], recursive: false, check: false, compact: false)
6
+ return {} if obj.nil?
7
+ obj||=self
8
+ stack=[*obj]
9
+ processed=[]
10
+ klass=stack.first.class
11
+ h={}
12
+ while !stack.empty?
13
+ obj=stack.shift
14
+ next if processed.include?(obj)
15
+ processed << obj
16
+ attributes={}
17
+ methods.each do |m|
18
+ next if check and !obj.respond_to? m
19
+ v=obj.public_send(m)
20
+ attributes[m]=v
21
+ if recursive
22
+ vals=v.kind_of?(Enumerable) ? v.to_a.flatten : [v]
23
+ vals.select! {|v| v.kind_of?(klass)}
24
+ stack.concat(vals)
25
+ end
26
+ end
27
+ attributes=attributes.values.first if compact and attributes.keys.length == 1
28
+ h[obj]=attributes
29
+ end
30
+ h
31
+ end
32
+ end
33
+ end
File without changes
@@ -0,0 +1,284 @@
1
+ module DR
2
+ class Eruby
3
+ module BindingHelper
4
+ extend self
5
+ #complement TOPLEVEL_BINDING
6
+ def empty_binding
7
+ #wraps into anonymous module so that 'def foo' do not pollute namespace
8
+ Module.new do
9
+ #regenerate a new binding
10
+ return binding
11
+ end
12
+ end
13
+ #empty binding (at first) that stays the same and can be shared
14
+ EMPTY_BINDING = empty_binding
15
+ BLANK_OBJECT=Object.new
16
+
17
+ # add variables values to a binding; variables is a Hash
18
+ def add_variables(variables, _binding=empty_binding)
19
+ eval variables.collect{|k,v| "#{k} = variables[#{k.inspect}]; "}.join, _binding
20
+ _binding
21
+ end
22
+
23
+ #From Tilt/template.rb
24
+ #return a string extracting local_keys from a hash named _context
25
+ def local_extraction(local_keys, context_name: '_context')
26
+ local_keys.map do |k|
27
+ if k.to_s =~ /\A[a-z_][a-zA-Z_0-9]*\z/
28
+ "#{k} = #{context_name}[#{k.inspect}]"
29
+ else
30
+ raise "invalid locals key: #{k.inspect} (keys must be variable names)"
31
+ end
32
+ end.join("\n")+"\n"
33
+ end
34
+
35
+ end
36
+
37
+ module EngineHelper
38
+ ### Stolen from erubis
39
+ ## eval(@src) with binding object
40
+ def result(_binding_or_hash=BindingHelper.empty_binding)
41
+ _arg = _binding_or_hash
42
+ if _arg.is_a?(Hash)
43
+ _b=BindingHelper.add_variables(_arg, BindingHelper.empty_binding)
44
+ elsif _arg.is_a?(Binding)
45
+ _b = _arg
46
+ elsif _arg.nil?
47
+ _b = binding
48
+ else
49
+ raise ArgumentError.new("#{self.class.name}#result(): argument should be Binding or Hash but passed #{_arg.class.name} object.")
50
+ end
51
+ return eval(@src, _b, (@filename || '(eruby'))
52
+ #erb.rb:
53
+ # if @safe_level
54
+ # proc {
55
+ # $SAFE = @safe_level
56
+ # eval(@src, b, (@filename || '(erb)'), @lineno)
57
+ # }.call
58
+ end
59
+
60
+ #Note that when the result is not used afterwards via "instance_eval"
61
+ #then the Klass of binding is important when src has 'def foo...'
62
+ #If set, locals should be an array of variable names
63
+ def compile(wrap: :proc, bind: BindingHelper.empty_binding, locals: nil, pre: nil, post: nil, context_name: '_context')
64
+ src=@src
65
+ src=BindingHelper.local_extraction(locals, context_name: context_name)+src if locals
66
+ src=pre+"\n"+src if pre
67
+ src<< post+"\n" if post
68
+ to_eval=case wrap
69
+ when :eval; @src
70
+ when :lambda; "lambda { |#{context_name}| #{src} }"
71
+ when :proc; "Proc.new { |#{context_name}| #{src} }"
72
+ when :module; "Module.new { |#{context_name}| #{src} }"
73
+ when :unbound
74
+ #wrapping in a method allows us to pass a block to a code
75
+ #calling yield
76
+ require 'dr/ruby_ext/meta_ext'
77
+ return Meta.get_unbound_evalmethod('eruby', src, args: context_name)
78
+ when :unbound_instance
79
+ #here we wrap in a method that the calls instance_eval
80
+ require 'dr/ruby_ext/meta_ext'
81
+ return Meta.get_unbound_evalmethod('eruby', <<-RUBY, args: context_name)
82
+ self.instance_eval do
83
+ #{src}
84
+ end
85
+ RUBY
86
+ when :string
87
+ src.to_s
88
+ else
89
+ warn "wrap meth #{warn} not understood, defaulting to String"
90
+ src
91
+ end
92
+ return eval(to_eval, bind, "(wrap #{@filename})")
93
+ end
94
+
95
+ ## by default invoke context.instance_eval(@src)
96
+ def evaluate(_context=Context.new, compile: {}, **opts, &b)
97
+ #I prefer to pass context as a keyword, but we allow to pass it as
98
+ #an argument to respect erubis's api
99
+ _context=opts[:context] if opts.key?(:context)
100
+ _context = Context.new(_context) if _context.is_a?(Hash)
101
+ vars=opts[:vars]
102
+ compile[:locals]||=vars.keys if vars
103
+ #to pass a block we need to wrap in a method
104
+ compile[:wrap]||=:unbound_instance if b
105
+ _proc=compile(**compile)
106
+ Eruby.evaluate(_proc, context: _context, **opts, &b)
107
+ end
108
+
109
+ ## if object is an Class or Module then define instance method to it,
110
+ ## else define singleton method to it.
111
+ def def_method(object, method_name, filename=nil)
112
+ m = object.is_a?(Module) ? :module_eval : :instance_eval
113
+ object.__send__(m, "def #{method_name}; #{@src}; end", filename || @filename || '(eruby)')
114
+ #erb.rb: src = self.src.sub(/^(?!#|$)/) {"def #{methodname}\n"} << "\nend\n" #This pattern insert the 'def' after lines with leading comments
115
+ end
116
+ end
117
+
118
+ class Template
119
+ include EngineHelper
120
+
121
+ def initialize(src, filename: nil)
122
+ if src.respond_to?(:read)
123
+ filename=src unless filename
124
+ src=src.read
125
+ end
126
+ @filename=filename || self.class.inspect
127
+ @src=src
128
+ end
129
+
130
+ end
131
+
132
+ module ClassHelpers
133
+ def process_eruby(eruby_src, **opts, &b)
134
+ src=Eruby::Engine.new(eruby_src).src
135
+ process_ruby(src, **opts, &b)
136
+ end
137
+
138
+ def process_ruby(src, src_info: nil, **opts, &b)
139
+ Template.new(src, filename: src_info).evaluate(**opts, &b)
140
+ end
141
+
142
+ def evaluate(_proc, context: Context.new, vars: nil, &b)
143
+ #we can only pass the block b when we get an UnboundMethod
144
+ if _proc.is_a?(UnboundMethod)
145
+ vars={} if _proc.arity > 0 and vars.nil?
146
+ if !vars.nil?
147
+ _proc.bind(context).call(vars,&b)
148
+ else
149
+ _proc.bind(context).call(&b)
150
+ end
151
+ elsif _proc.is_a?(String)
152
+ #in this case we cannot pass vars
153
+ warn "Cannot pass variables when _proc is a String" unless vars.nil?
154
+ context.instance_eval(_proc)
155
+ else
156
+ if context.nil?
157
+ if !vars.nil?
158
+ _proc.to_proc.call(vars,&b)
159
+ else
160
+ _proc.to_proc(&b)
161
+ end
162
+ else
163
+ warn "Cannot pass block in context.instance_eval" unless b.nil?
164
+ if !vars.nil?
165
+ context.instance_exec(vars,&_proc)
166
+ else
167
+ context.instance_eval(&_proc)
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+ def include(template, **opts)
174
+ file=File.expand_path(template)
175
+ Dir.chdir(File.dirname(file)) do |cwd|
176
+ erb = Engine.new(File.read(file))
177
+ #if context is not empty, then we probably want to evaluate
178
+ if opts[:evaluate] or opts[:context]
179
+ r=erb.evaluate(opts[:context])
180
+ else
181
+ bind=opts[:bind]||binding
182
+ r=erb.result(bind)
183
+ end
184
+ #if using erubis, it is better to invoke the template in <%= =%> than
185
+ #to use chomp=true
186
+ r=r.chomp if opts[:chomp]
187
+ return r
188
+ end
189
+ end
190
+ end
191
+
192
+ extend ClassHelpers
193
+
194
+ begin
195
+ require 'erubi'
196
+ Engine=::Erubi::Engine
197
+ rescue LoadError
198
+ require 'erubis'
199
+ Engine=::Erubis::Eruby
200
+ rescue LoadError
201
+ require 'erb'
202
+ Engine=::ERB
203
+ end
204
+ #prepend so that we have the same implementation
205
+ Engine.__send__(:prepend, EngineHelper)
206
+
207
+ ## Copy/Pasted from erubis context.rb
208
+ ## # context object for Engine#evaluate
209
+ ##
210
+ ## ex.
211
+ ## template = <<'END'
212
+ ## Hello <%= @user %>!
213
+ ## <% for item in @list %>
214
+ ## - <%= item %>
215
+ ## <% end %>
216
+ ## END
217
+ ##
218
+ ## context = Erubis::Context.new(:user=>'World', :list=>['a','b','c'])
219
+ ## # or
220
+ ## # context = Erubis::Context.new
221
+ ## # context[:user] = 'World'
222
+ ## # context[:list] = ['a', 'b', 'c']
223
+ ##
224
+ ## eruby = Erubis::Eruby.new(template)
225
+ ## print eruby.evaluate(context)
226
+ ##
227
+ class Context
228
+ include Enumerable
229
+
230
+ def initialize(hash=nil)
231
+ hash.each do |name, value|
232
+ self[name] = value
233
+ end if hash
234
+ end
235
+
236
+ def [](key)
237
+ return instance_variable_get("@#{key}")
238
+ end
239
+
240
+ def []=(key, value)
241
+ return instance_variable_set("@#{key}", value)
242
+ end
243
+
244
+ def keys
245
+ return instance_variables.collect { |name| name[1..-1] }
246
+ end
247
+
248
+ def each
249
+ instance_variables.each do |name|
250
+ key = name[1..-1]
251
+ value = instance_variable_get(name)
252
+ yield(key, value)
253
+ end
254
+ end
255
+
256
+ # Was to_hash, but changed to 'to_h' in commit 25d0e1e4b1a4ada40fd64945eb79823ea074d030
257
+ # Indeed otherwise passing it to 'evaluate' it get interpreted as the options rather than as a context
258
+ # cf https://bugs.ruby-lang.org/issues/12884
259
+ # corrected in ruby 2.4.1?
260
+ def to_h
261
+ hash = {}
262
+ self.keys.each { |key| hash[key] = self[key] }
263
+ return hash
264
+ end
265
+
266
+ def update(context_or_hash)
267
+ arg = context_or_hash
268
+ if arg.is_a?(Hash)
269
+ arg.each do |key, val|
270
+ self[key] = val
271
+ end
272
+ else
273
+ arg.instance_variables.each do |varname|
274
+ key = varname[1..-1]
275
+ val = arg.instance_variable_get(varname)
276
+ self[key] = val
277
+ end
278
+ end
279
+ end
280
+
281
+ end
282
+ end
283
+
284
+ end