drain 0.3.0 → 0.7.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 +4 -4
- data/.github/workflows/ruby.yml +25 -0
- data/.travis.yml +7 -3
- data/ChangeLog.md +159 -2
- data/Gemfile +4 -1
- data/LICENSE.txt +1 -1
- data/README.md +14 -3
- data/Rakefile +15 -10
- data/drain.gemspec +1 -0
- data/gemspec.yml +3 -3
- data/lib/dr/base/delegate.rb +28 -0
- data/lib/dr/base/graph.rb +26 -9
- data/lib/dr/base/uri.rb +224 -192
- data/lib/dr/base/utils.rb +39 -8
- data/lib/dr/parse/simple_keywords.rb +1 -1
- data/lib/dr/parse/time_parse.rb +29 -23
- data/lib/dr/ruby_ext/core_modules.rb +5 -3
- data/lib/dr/version.rb +1 -1
- data/test/helper.rb +12 -2
- data/test/test_converter.rb +7 -7
- data/test/test_core_ext.rb +24 -24
- data/test/test_date_parse.rb +8 -4
- data/test/test_graph.rb +26 -26
- data/test/test_meta.rb +3 -3
- data/test/test_simple_keywords.rb +6 -6
- data/test/test_simple_parser.rb +9 -9
- data/test/test_time_parse.rb +43 -0
- data/test/test_uri.rb +35 -0
- metadata +20 -16
data/lib/dr/base/uri.rb
CHANGED
@@ -2,200 +2,232 @@ require "uri"
|
|
2
2
|
require "delegate"
|
3
3
|
|
4
4
|
module URI
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
5
|
+
# From https://github.com/packsaddle/ruby-uri-ssh_git
|
6
|
+
module Ssh
|
7
|
+
extend self
|
8
|
+
# @example
|
9
|
+
# url = URI::Ssh.parse('git@github.com:packsaddle/ruby-uri-ssh_git.git')
|
10
|
+
# #=> #<URI::Ssh::Generic git@github.com:packsaddle/ruby-uri-ssh_git.git>
|
11
|
+
# url.scheme #=> nil
|
12
|
+
# url.userinfo #=> 'git'
|
13
|
+
# url.user #=> 'git'
|
14
|
+
# url.password #=> nil
|
15
|
+
# url.host #=> 'github.com'
|
16
|
+
# url.port #=> nil
|
17
|
+
# url.registry #=> nil
|
18
|
+
# url.path #=> 'packsaddle/ruby-uri-ssh_git.git'
|
19
|
+
# url.opaque #=> nil
|
20
|
+
# url.query #=> nil
|
21
|
+
# url.fragment #=> nil
|
22
|
+
# @see http://docs.ruby-lang.org/en/2.2.0/URI/Generic.html
|
23
|
+
# @param url [String] git repository url via ssh protocol
|
24
|
+
# @return [Generic] parsed object
|
25
|
+
protected def internal_parse(uri_string)
|
26
|
+
host_part, path_part = uri_string&.split(':', 2)
|
27
|
+
# There may be no user, so reverse the split to make sure host always
|
28
|
+
# is !nil if host_part was !nil.
|
29
|
+
host, userinfo = host_part&.split('@', 2)&.reverse
|
30
|
+
Generic.build(userinfo: userinfo, host: host || uri_string, path: path_part)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param url [String] git repository-ish url
|
34
|
+
# @return [URI::Generic] if url starts ssh
|
35
|
+
# @return [URI::HTTPS] if url starts https
|
36
|
+
# @return [URI::SshGit] if url is ssh+git e.g git@example.com:schacon/ticgit.git
|
37
|
+
def parse(url, force: false)
|
38
|
+
(ssh_git_url?(url) || force)? ::URI::Ssh.internal_parse(url) : ::URI.parse(url)
|
39
|
+
end
|
40
|
+
|
41
|
+
## From: https://github.com/packsaddle/ruby-git_clone_url
|
42
|
+
# @param url [String] git repository-ish url
|
43
|
+
# @return [Boolean] true if url is git via ssh protocol
|
44
|
+
def ssh_git_url?(url)
|
45
|
+
!generic_url?(url)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param url [String] git repository-ish url
|
49
|
+
# @return [Boolean] true if url is https, ssh protocol
|
50
|
+
def generic_url?(url)
|
51
|
+
match = %r{\A(\w*)://}.match(url)
|
52
|
+
!match.nil?
|
53
|
+
end
|
54
|
+
|
55
|
+
class Generic < ::URI::Generic #URI::Ssh::Generic
|
56
|
+
# check_host returns `false` for 'foo_bar'
|
57
|
+
# but in ssh config this can be a valid host
|
58
|
+
def check_host(_v)
|
59
|
+
return true
|
60
|
+
end
|
61
|
+
# @example
|
62
|
+
# URI::Ssh::Generic.build(
|
63
|
+
# userinfo: 'git',
|
64
|
+
# host: 'github.com',
|
65
|
+
# path: 'packsaddle/ruby-uri-ssh_git.git'
|
66
|
+
# ).to_ssh
|
67
|
+
# #=> 'git@github.com:packsaddle/ruby-uri-ssh_git.git'
|
68
|
+
#
|
69
|
+
# @return [String] git repository url via ssh protocol
|
70
|
+
def to_ssh(show_path: true)
|
71
|
+
str = ''
|
72
|
+
str << "#{user}@" if user && !user.empty?
|
73
|
+
str << "#{host}"
|
74
|
+
str << ":#{path}" if path and show_path
|
75
|
+
str
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
79
|
end
|
80
80
|
|
81
81
|
module DR
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
82
|
+
module URI
|
83
|
+
module MailToHelper
|
84
|
+
# TODO: wrap to= to add user= and host=
|
85
|
+
end
|
86
|
+
|
87
|
+
module URIHelpers
|
88
|
+
def to_h
|
89
|
+
h = { uri: uri }
|
90
|
+
components = uri.component
|
91
|
+
components += %i[user password] if components.include?(:userinfo)
|
92
|
+
components.each do |m|
|
93
|
+
v = uri.public_send(m)
|
94
|
+
v && h[m] = v
|
95
|
+
end
|
96
|
+
h
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_json(_state = nil)
|
100
|
+
h=to_h
|
101
|
+
h[:uri]=h[:uri].to_s #h[:uri] is a URIWrapper, so convert it to string so json does not convert it again
|
102
|
+
h.to_json
|
103
|
+
end
|
104
|
+
|
105
|
+
# strip password
|
106
|
+
def to_public
|
107
|
+
pub = dup
|
108
|
+
pub.password = nil
|
109
|
+
pub.to_s
|
110
|
+
end
|
111
|
+
|
112
|
+
def strip_user
|
113
|
+
pub = dup
|
114
|
+
pub.user = nil
|
115
|
+
pub.to_s
|
116
|
+
end
|
117
|
+
|
118
|
+
# uri=u2.merge(uri) does not work if uri is absolute
|
119
|
+
def reverse_merge(u2)
|
120
|
+
# return self unless uri.scheme
|
121
|
+
u2 = u2.clone
|
122
|
+
u2 = self.class.new(u2) unless u2.is_a?(self.class)
|
123
|
+
if opaque.nil? == u2.opaque.nil?
|
124
|
+
u2.soft_merge(self)
|
125
|
+
else
|
126
|
+
self
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# merge(u2) replace self by u2 if u2 is aboslute
|
131
|
+
# soft_merge looks at each u2 components
|
132
|
+
def soft_merge(u2)
|
133
|
+
# we want automatic unescaping of u2 components
|
134
|
+
u2 = self.class.new(u2) unless u2.is_a?(self.class)
|
135
|
+
# only merge if we are both opaque or path like
|
136
|
+
if opaque.nil? == u2.opaque.nil?
|
137
|
+
components = uri.component
|
138
|
+
if components.include?(:userinfo)
|
139
|
+
components += %i[user password]
|
140
|
+
components.delete(:userinfo)
|
141
|
+
end
|
142
|
+
components.each do |m|
|
143
|
+
# path returns "" by default but we don't want to merge in this case
|
144
|
+
if u2.respond_to?(m) && (v = u2.public_send(m)) && !((v == "") && (m == :path))
|
145
|
+
uri.public_send(:"#{m}=", v)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
self
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class Wrapper < SimpleDelegator
|
154
|
+
def uri
|
155
|
+
__getobj__
|
156
|
+
end
|
157
|
+
|
158
|
+
def uri=(uri)
|
159
|
+
__setobj__(transform_uri(uri))
|
160
|
+
end
|
161
|
+
|
162
|
+
include URIHelpers
|
163
|
+
|
164
|
+
def self.parse(s)
|
165
|
+
new(::URI.parse(s))
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.get_uri_object(uri)
|
169
|
+
uri = self.parse(uri.to_s) unless uri.is_a?(::URI)
|
170
|
+
uri
|
171
|
+
end
|
172
|
+
|
173
|
+
private def transform_uri(uri)
|
174
|
+
# wrap the components around escape/unescape
|
175
|
+
uri = self.class.get_uri_object(uri)
|
176
|
+
if uri.is_a?(::URI::Generic)
|
177
|
+
uri.extend(URI::MailToHelper) if uri.is_a?(::URI::MailTo)
|
178
|
+
components = uri.component
|
179
|
+
components += %i[user password] if components.include?(:userinfo)
|
180
|
+
components.each do |m|
|
181
|
+
uri.define_singleton_method(m) do
|
182
|
+
r = super()
|
183
|
+
r && r.is_a?(String) ? URI.unescape(r) : r
|
184
|
+
# r && r.is_a?(String) ? ::URI.decode_www_form_component(r) : r
|
185
|
+
end
|
186
|
+
uri.define_singleton_method(:"#{m}=") do |v|
|
187
|
+
begin
|
188
|
+
super(v && v.is_a?(String) ? URI.escape(v) : v)
|
189
|
+
# super(v && v.is_a?(String) ? ::URI.encode_www_form_component(v) : v)
|
190
|
+
rescue ::URI::InvalidURIError => e
|
191
|
+
warn "#{e} in (#{self}).#{m}=#{v}"
|
192
|
+
# require 'pry'; binding.pry
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
uri
|
198
|
+
end
|
199
|
+
|
200
|
+
# recall that '//user@server' is an uri while 'user@server' is just a path
|
201
|
+
def initialize(uri)
|
202
|
+
super
|
203
|
+
self.uri = uri
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class Ssh < Wrapper
|
208
|
+
def self.parse(s)
|
209
|
+
new(::URI::Ssh.parse(s))
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# reimplement deprecated escape and unescape methods since
|
214
|
+
# URI.encode_www_form_component does not encode the same way
|
215
|
+
# cf the source code of URI::DEFAULT_PARSER.escape
|
216
|
+
module URIEscape
|
217
|
+
extend self
|
218
|
+
def escape(*arg)
|
219
|
+
::URI::DEFAULT_PARSER.escape(*arg)
|
220
|
+
end
|
221
|
+
def unescape(*arg)
|
222
|
+
::URI::DEFAULT_PARSER.unescape(*arg)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
Escape=URIEscape
|
226
|
+
extend URIEscape
|
227
|
+
|
228
|
+
def self.parse(s)
|
229
|
+
Wrapper.parse(s)
|
230
|
+
end
|
231
|
+
end
|
200
232
|
|
201
233
|
end
|
data/lib/dr/base/utils.rb
CHANGED
@@ -1,23 +1,36 @@
|
|
1
1
|
module DR
|
2
2
|
module Utils
|
3
3
|
extend self
|
4
|
-
def pretty_print(string, format: nil, pretty:
|
4
|
+
def pretty_print(string, format: nil, pretty: nil, **kw)
|
5
5
|
case format.to_s
|
6
6
|
when "json"
|
7
7
|
require 'json'
|
8
|
-
return pretty_print(string.to_json, pretty: pretty)
|
8
|
+
return pretty_print(string.to_json, pretty: pretty, **kw)
|
9
9
|
when "yaml"
|
10
10
|
require "yaml"
|
11
|
-
return pretty_print(string.to_yaml, pretty: pretty)
|
11
|
+
return pretty_print(string.to_yaml, pretty: pretty, **kw)
|
12
12
|
end
|
13
|
-
if pretty
|
13
|
+
pretty = "color" if pretty == nil or pretty == true #default
|
14
|
+
case pretty.to_s
|
15
|
+
when "ap", "awesome_print", "amazing_print"
|
14
16
|
begin
|
15
|
-
require '
|
16
|
-
ap
|
17
|
+
require 'amazing_print'
|
18
|
+
ap(string, **kw)
|
17
19
|
rescue LoadError,NameError
|
18
|
-
pretty_print(string,pretty:
|
20
|
+
pretty_print(string,pretty: :pp_color, **kw)
|
19
21
|
end
|
20
|
-
|
22
|
+
when "color", "pp_color"
|
23
|
+
begin
|
24
|
+
require 'pry'
|
25
|
+
if kw[:multiline] == false #simulate no multiline
|
26
|
+
Pry::ColorPrinter.pp string, $DEFAULT_OUTPUT, 9999
|
27
|
+
else
|
28
|
+
Pry::ColorPrinter.pp string
|
29
|
+
end
|
30
|
+
rescue LoadError,NameError
|
31
|
+
pretty_print(string,pretty: :pp)
|
32
|
+
end
|
33
|
+
when "pp"
|
21
34
|
require 'pp'
|
22
35
|
pp string
|
23
36
|
else
|
@@ -49,4 +62,22 @@ module DR
|
|
49
62
|
end
|
50
63
|
end
|
51
64
|
end
|
65
|
+
|
66
|
+
# Include this to get less output from pp
|
67
|
+
module PPHelper
|
68
|
+
# less verbose for pretty_print
|
69
|
+
def pretty_print(pp)
|
70
|
+
info = respond_to?(:to_pp) ? to_pp : to_s
|
71
|
+
pp.object_address_group(self) { pp.text " "+info }
|
72
|
+
end
|
73
|
+
|
74
|
+
#since we hide the pp value of self, allow to inspect it
|
75
|
+
def export
|
76
|
+
r={}
|
77
|
+
instance_variables.sort.each do |var|
|
78
|
+
r[var]=instance_variable_get(var)
|
79
|
+
end
|
80
|
+
r
|
81
|
+
end
|
82
|
+
end
|
52
83
|
end
|