epitools 0.4.15 → 0.4.16

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.
@@ -3,15 +3,15 @@
3
3
  Useful miscellaneous improvements for base Ruby objects, plus some extra
4
4
  data structures and handy wrappers.
5
5
 
6
- Base classess: Object, Enumerable, Hash, String, Array, Integer, etc.
6
+ Base classess have been enhanced: {Enumerable}[http://rdoc.info/gems/epitools/Enumerable], {Hash}[http://rdoc.info/gems/epitools/Hash], {String}[http://rdoc.info/gems/epitools/String], {Array}[http://rdoc.info/gems/epitools/Array], {Object}[http://rdoc.info/gems/epitools/Object], {Integer}[http://rdoc.info/gems/epitools/Integer], etc.
7
7
 
8
8
  Extras:
9
9
 
10
- * Path (a better Pathname)
11
- * Rash (a hash which can have Regexps as keys, allowing a single (key,value) pair to match many keys.)
12
- * Progressbar (better than the progressbar gem)
13
- * Colored (enhanced version of defunkt's colored -- adds ANSI colouring methods to String, eg: #red, #green, #light_blue, etc.)
14
- * Browser (a fake browser, using mechanize, Progressbar, and CacheDB)
10
+ * {Colored}[http://rdoc.info/gems/epitools/Colored] (enhanced version of defunkt's colored -- adds ANSI colouring methods to String, eg: #red, #green, #light_blue, etc.)
11
+ * {Path}[http://rdoc.info/gems/epitools/Path] (a better Pathname)
12
+ * {Rash}[http://rdoc.info/gems/epitools/Rash] (a hash which can have Regexps as keys, allowing a single (key,value) pair to match many keys.)
13
+ * {Progressbar}[http://rdoc.info/gems/epitools/Progressbar] (better than the progressbar gem)
14
+ * {Browser}[http://rdoc.info/gems/epitools/Browser] (a fake browser, using mechanize, Progressbar, and CacheDB)
15
15
 
16
16
  == Installing
17
17
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.15
1
+ 0.4.16
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{epitools}
8
- s.version = "0.4.15"
8
+ s.version = "0.4.16"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["epitron"]
12
- s.date = %q{2011-03-14}
12
+ s.date = %q{2011-03-15}
13
13
  s.description = %q{Miscellaneous utility libraries to make my life easier.}
14
14
  s.email = %q{chris@ill-logic.com}
15
15
  s.extra_rdoc_files = [
@@ -31,7 +31,6 @@ Gem::Specification.new do |s|
31
31
  "lib/epitools/clitools.rb",
32
32
  "lib/epitools/colored.rb",
33
33
  "lib/epitools/hexdump.rb",
34
- "lib/epitools/http.rb",
35
34
  "lib/epitools/lcs.rb",
36
35
  "lib/epitools/metaclass.rb",
37
36
  "lib/epitools/niceprint.rb",
@@ -15,6 +15,7 @@ class Object
15
15
  end
16
16
 
17
17
  require_wrapper = proc do |mod|
18
+ #p [:loading, mod]
18
19
  begin
19
20
  require File.join(__DIR__, "epitools", mod)
20
21
  rescue LoadError => e
@@ -32,6 +33,7 @@ end
32
33
  zopen
33
34
  colored
34
35
  clitools
36
+ permutations
35
37
  ].each do |mod|
36
38
  require_wrapper.call mod
37
39
  end
@@ -29,10 +29,16 @@ class Numeric
29
29
  end
30
30
 
31
31
  class Float
32
+ #
33
+ # 'true' if the float is 0.0
34
+ #
32
35
  def blank?; self == 0.0; end
33
36
  end
34
37
 
35
38
  class NilClass
39
+ #
40
+ # Always 'true'; nil is considered blank.
41
+ #
36
42
  def blank?; true; end
37
43
  end
38
44
 
@@ -45,6 +51,9 @@ class String
45
51
  strip.match(/^\d+$/) ? true : false
46
52
  end
47
53
 
54
+ #
55
+ # 'true' if the string's length is 0 (after whitespace has been stripped from the ends)
56
+ #
48
57
  def blank?
49
58
  strip.size == 0
50
59
  end
@@ -91,6 +100,9 @@ end
91
100
 
92
101
  class Integer
93
102
 
103
+ #
104
+ # 'true' if the integer is 0
105
+ #
94
106
  def blank?; self == 0; end
95
107
 
96
108
  def to_hex
@@ -140,6 +152,9 @@ end
140
152
 
141
153
  class Array
142
154
 
155
+ #
156
+ # 'true' if the Array is empty
157
+ #
143
158
  def blank?; not self.any?; end
144
159
 
145
160
  #
@@ -191,6 +206,9 @@ end
191
206
 
192
207
  module Enumerable
193
208
 
209
+ #
210
+ # 'true' if the Enumerable has no elements
211
+ #
194
212
  def blank?
195
213
  not self.any?
196
214
  end
@@ -378,9 +396,10 @@ module Enumerable
378
396
  select.with_index{ |e, i| bitmask[i] == 1 }
379
397
  end
380
398
  end
381
-
399
+
382
400
  end
383
401
 
402
+
384
403
  class Object
385
404
 
386
405
  #
@@ -438,14 +457,14 @@ class Object
438
457
 
439
458
  #
440
459
  # A decorator that makes any block-accepting method return an
441
- # Enumerable::Enumerator whenever the method is called without a block.
460
+ # Enumerator whenever the method is called without a block.
442
461
  #
443
462
  def self.enumerable *meths
444
463
  meths.each do |meth|
445
464
  alias_method "#{meth}_without_enumerator", meth
446
465
  class_eval %{
447
466
  def #{meth}(*args, &block)
448
- return Enumerable::Enumerator.new(self, #{meth.inspect}, *args, &block) unless block_given?
467
+ return Enum.new(self, #{meth.inspect}, *args, &block) unless block_given?
449
468
  #{meth}_without_enumerator(*args, &block)
450
469
  end
451
470
  }
@@ -457,12 +476,15 @@ end
457
476
 
458
477
  class Hash
459
478
 
479
+ #
480
+ # 'true' if the Hash has no entries
481
+ #
460
482
  def blank?
461
483
  not self.any?
462
484
  end
463
485
 
464
486
  #
465
- # Runs remove_blank_lines on self.
487
+ # Runs "remove_blank_values" on self.
466
488
  #
467
489
  def remove_blank_values!
468
490
  delete_if{|k,v| v.blank?}
@@ -470,8 +492,8 @@ class Hash
470
492
  end
471
493
 
472
494
  #
473
- # Returns a new Hash where all elements whose values are "blank?" (eg: "", [], nil)
474
- # have been eliminated.
495
+ # Returns a new Hash where blank values have been removed.
496
+ # (It checks if the value is blank by calling #blank? on it)
475
497
  #
476
498
  def remove_blank_values
477
499
  dup.remove_blank_values!
@@ -489,7 +511,8 @@ class Hash
489
511
  end
490
512
 
491
513
  #
492
- # Returns a Hash whsoe values have been transformed by the block.
514
+ # Transforms the values of the hash by passing them into the supplied
515
+ # block, and then using the block's result as the new value.
493
516
  #
494
517
  def map_values(&block)
495
518
  dup.map_values!(&block)
@@ -507,15 +530,15 @@ class Hash
507
530
  end
508
531
 
509
532
  #
510
- # Returns a new Hash whose keys have been transformed by the block.
533
+ # Transforms the keys of the hash by passing them into the supplied block,
534
+ # and then using the blocks result as the new key.
511
535
  #
512
536
  def map_keys(&block)
513
537
  dup.map_keys!(&block)
514
538
  end
515
539
 
516
540
  #
517
- # Creates an new Hash whose missing items default to [].
518
- # Good for collecting things!
541
+ # Returns a new Hash whose values default to empty arrays. (Good for collecting things!)
519
542
  #
520
543
  # eg:
521
544
  # Hash.of_arrays[:yays] << "YAY!"
@@ -525,8 +548,7 @@ class Hash
525
548
  end
526
549
 
527
550
  #
528
- # Creates an new Hash whose missing items default to values of 0.
529
- # Good for counting things!
551
+ # Returns a new Hash whose values default to 0. (Good for counting things!)
530
552
  #
531
553
  # eg:
532
554
  # Hash.of_integers[:yays] += 1
@@ -572,7 +594,7 @@ protected
572
594
  end
573
595
 
574
596
 
575
- class It < BlankSlate
597
+ class It < BlankSlate # :nodoc:
576
598
  #undef_method( *(instance_methods - ["__id__", "__send__"]) )
577
599
 
578
600
  def initialize
@@ -593,7 +615,7 @@ class It < BlankSlate
593
615
  end
594
616
  end
595
617
 
596
- class NotWrapper < BlankSlate
618
+ class NotWrapper < BlankSlate # :nodoc:
597
619
  def initialize(orig)
598
620
  @orig = orig
599
621
  end
@@ -8,7 +8,7 @@ require 'epitools/browser/mechanize_progressbar'
8
8
 
9
9
  # TODO: Make socksify optional (eg: if proxy is specified)
10
10
  #require 'socksify'
11
- class SOCKSError < Exception; end
11
+ class SOCKSError < Exception; end # :nodoc:
12
12
 
13
13
  # TODO: Put options here.
14
14
  =begin
@@ -1,6 +1,9 @@
1
1
  require 'mechanize'
2
2
  require 'sqlite3'
3
3
 
4
+ #
5
+ # Emit a quick debug message (only if $DEBUG is true)
6
+ #
4
7
  def dmsg(msg)
5
8
 
6
9
  if $DEBUG
@@ -5,7 +5,7 @@ require 'epitools/progressbar'
5
5
  #
6
6
  # (Displays a progress bar whenever an url is retrieved.)
7
7
  #
8
- class Mechanize
8
+ class Mechanize # :nodoc: all
9
9
  class Chain
10
10
  class ResponseReader
11
11
  include Mechanize::Handler
@@ -1,23 +1,31 @@
1
1
  require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /win32/
2
2
  require 'set'
3
3
 
4
- ##
5
- # cute.
6
- #
7
- # >> "this is red".red
4
+ #
5
+ # ANSI Colour-coding for terminals that support it.
6
+ # Originally by defunkt (Chris Wanstrath)
7
+ #
8
+ # It extends String with methods that insert terminal codes.
9
+ #
10
+ # Examples:
11
+ #
12
+ # >> "this is red".red
8
13
  #
9
- # >> "this is red with a blue background (read: ugly)".red_on_blue
14
+ # >> "this is red with a blue background (read: ugly)".red_on_blue
15
+ #
16
+ # >> "this is light blue".light_blue
10
17
  #
11
- # >> "this is red with an underline".red.underline
18
+ # >> "<yellow>This is using <green>tags</green> to colorize.".colorize
12
19
  #
13
- # >> "this is really bold and really blue".bold.blue
20
+ # >> "this is red with an underline".red.underline
21
+ #
22
+ # >> "this is really bold and really blue".bold.blue
23
+ #
24
+ # >> Colored.red "This is red" # but this part is mostly untested
14
25
  #
15
- # >> Colored.red "This is red" # but this part is mostly untested
16
26
  module Colored
17
27
  extend self
18
28
 
19
- ###########################################################################
20
-
21
29
  @@is_tty = STDOUT.isatty
22
30
 
23
31
  COLORS = {
@@ -67,8 +75,6 @@ module Colored
67
75
  COLORS.map { |k,v| "bold_#{k}" }
68
76
  )
69
77
 
70
- ###########################################################################
71
-
72
78
  COLORS.each do |color, value|
73
79
  define_method(color) do
74
80
  colorize(self, :foreground => color)
@@ -171,7 +177,8 @@ module Colored
171
177
  alias_method :is_tty?, :enabled?
172
178
 
173
179
  #
174
- # Color commands will always produce colored strings.
180
+ # Color commands will always produce colored strings, regardless
181
+ # of whether the script is being run in a terminal.
175
182
  #
176
183
  def enable!
177
184
  @@is_tty = true
@@ -262,7 +269,6 @@ module Colored
262
269
  result
263
270
  end
264
271
 
265
-
266
272
  end unless Object.const_defined? :Colored
267
273
 
268
274
  String.send(:include, Colored)
@@ -1,4 +1,4 @@
1
- %w[rubygems colorize].each{|r| require r}
1
+ require 'colored'
2
2
 
3
3
  ASCII_PRINTABLE = (33..126)
4
4
 
@@ -73,19 +73,26 @@ class Path
73
73
 
74
74
 
75
75
  ## getters
76
-
77
- attr_reader :dirs, :base, :ext
76
+
77
+ # The path's directories as an array. (eg: ['usr', 'src', 'linux'])
78
+ attr_reader :dirs
79
+
80
+ # The filename without an extension
81
+ attr_reader :base
78
82
 
83
+ # The file extension, including the . (eg: ".mp3")
84
+ attr_reader :ext
85
+
86
+ # Joins and returns the full path
79
87
  def path
80
- d = dir
81
- f = filename
82
- if d
83
- File.join(d, (f || "") )
88
+ if d = dir
89
+ File.join(d, (filename || "") )
84
90
  else
85
91
  ""
86
92
  end
87
93
  end
88
94
 
95
+ # The current directory (with a trailing /)
89
96
  def dir
90
97
  if dirs
91
98
  File::SEPARATOR + File.join(*dirs)
@@ -159,7 +166,18 @@ class Path
159
166
  self.path <=> other.path
160
167
  end
161
168
 
162
- ## opening/reading
169
+
170
+ ## appending
171
+
172
+ #
173
+ # Path["/etc"]/"passwd" == Path["/etc/passwd"]
174
+ #
175
+ def /(other)
176
+ Path.new( File.join(self, other) )
177
+ end
178
+
179
+
180
+ ## opening/reading files
163
181
 
164
182
  def open(mode="rb", &block)
165
183
  if block_given?
@@ -174,3 +192,10 @@ class Path
174
192
  end
175
193
 
176
194
  end
195
+
196
+ #
197
+ # Path("/some/path") is the same as Path["/some/path"]
198
+ #
199
+ def Path(*args)
200
+ Path[*args]
201
+ end
@@ -2,7 +2,7 @@ require 'epitools/basetypes'
2
2
 
3
3
  class Array
4
4
 
5
- alias_method :"original_*_for_cartesian_*", :*
5
+ alias_method :"*_without_permutations", :*
6
6
 
7
7
  #
8
8
  # Overloaded * operator.
@@ -24,7 +24,7 @@ class Array
24
24
  end
25
25
  result
26
26
  else
27
- send(:"original_*_for_cartesian_*", other)
27
+ send(:"*_without_permutations", other)
28
28
  end
29
29
  end
30
30
 
@@ -35,6 +35,17 @@ class Array
35
35
  ([self] * exponent).foldl(:*)
36
36
  end
37
37
 
38
+ def all_pairs(reflexive=false)
39
+ (0...size).each do |a|
40
+ start = reflexive ? a : a+1
41
+ (start...size).each do |b|
42
+ yield self[a], self[b]
43
+ end
44
+ end
45
+ end
46
+
47
+ enumerable :all_pairs
48
+
38
49
  end
39
50
 
40
51
 
@@ -5,32 +5,7 @@ require 'colorize'
5
5
  # TODO: Pick a backtrace format. (Also, add a method to replace default backtracer.)
6
6
  # TODO: This chould be in a class.
7
7
 
8
- class Array
9
-
10
- def split_when(&block)
11
-
12
- chunks = []
13
- start = 0
14
-
15
- for i in 0...self.size-1
16
-
17
- split_here = yield(self[i], self[i+1])
18
- if split_here
19
- chunks << self[start..i]
20
- start = i+1
21
- end
22
-
23
- end
24
-
25
- chunks << self[start..-1]
26
- chunks
27
-
28
- end
29
-
30
- end
31
-
32
-
33
- class Line
8
+ class Line # :nodoc:
34
9
 
35
10
  attr_accessor :path, :num, :meth, :dir, :filename
36
11
 
@@ -79,7 +54,7 @@ end
79
54
 
80
55
 
81
56
  def color_backtrace_1(lines)
82
- groups = lines.split_when { |line,nextline| line.path != nextline.path }
57
+ groups = lines.split_before { |line,nextline| line.path != nextline.path }
83
58
  for group in groups
84
59
  dir, filename = File.split(group.first.path)
85
60
  puts "#{filename.green} (#{dir.light_white})"
@@ -1,5 +1,11 @@
1
1
  #
2
- # A Regex-queryable Hash
2
+ # A Regex-queryable Hash.
3
+ #
4
+ # Usage:
5
+ #
6
+ # greeting = Rash.new( /^Mr./ => "Hello sir!", /^Mrs./ => "Evening, madame." )
7
+ # greeting["Mr. Steve Austin"] #=> "Hello sir!"
8
+ # greeting["Mrs. Steve Austin"] #=> "Evening, madame."
3
9
  #
4
10
  class Rash
5
11
 
@@ -17,7 +23,7 @@ class Rash
17
23
 
18
24
  def []=(key, value)
19
25
  if key.is_a? Regexp
20
- key = normalize_regex(key)
26
+ #key = normalize_regex(key) # this used to just do: /#{regexp}/
21
27
  @regexes << key
22
28
  end
23
29
  @hash[key] = value
@@ -83,10 +89,5 @@ private
83
89
  end
84
90
  end
85
91
 
86
- def normalize_regex(regex)
87
- #/^#{regex}$/
88
- regex
89
- end
90
-
91
92
  end
92
93
 
@@ -2,7 +2,7 @@
2
2
  # Cross-platform operating system functions.
3
3
  # Includes: process listing, platform detection, etc.
4
4
  #
5
- require 'metaclass'
5
+ require 'epitools/metaclass'
6
6
 
7
7
  module Sys
8
8
 
@@ -208,7 +208,7 @@ describe Enumerable do
208
208
  it "powersets" do
209
209
  [1,2,3].powerset.should == [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
210
210
  end
211
-
211
+
212
212
  end
213
213
 
214
214
  describe Hash do
@@ -1,3 +1,4 @@
1
+ require 'epitools/permutations'
1
2
  require 'epitools/path'
2
3
 
3
4
  describe Path do
@@ -101,4 +102,19 @@ describe Path do
101
102
  s2[15..-1].should == s1
102
103
  end
103
104
 
105
+ it "makes paths THREE WAYS!" do
106
+ [
107
+ Path(__FILE__),
108
+ Path[__FILE__],
109
+ Path.new(__FILE__),
110
+ ].all_pairs do |p1, p2|
111
+ p1.path.should == p2.path
112
+ end
113
+ end
114
+
115
+ it "appending to paths with /" do
116
+ ( Path['/etc']/'passwd' ).should == Path['/etc/passwd']
117
+ ( Path['/etc']/Path['passwd'] ).should_not == Path['/etc/passwd']
118
+ end
119
+
104
120
  end
@@ -11,4 +11,25 @@ describe "Permutations" do
11
11
  ([1,2] ** 2).should == [ [1,1], [1,2], [2,1], [2,2] ]
12
12
  end
13
13
 
14
+ it "all_pairses" do
15
+ [1,2,3,4].all_pairs.to_a.should == [
16
+ [1,2],
17
+ [1,3],
18
+ [1,4],
19
+ [2,3],
20
+ [2,4],
21
+ [3,4],
22
+ ]
23
+
24
+ # reflexive
25
+ [1,2,3].all_pairs(true).to_a.should == [
26
+ [1,1],
27
+ [1,2],
28
+ [1,3],
29
+ [2,2],
30
+ [2,3],
31
+ [3,3],
32
+ ]
33
+ end
34
+
14
35
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: epitools
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.15
5
+ version: 0.4.16
6
6
  platform: ruby
7
7
  authors:
8
8
  - epitron
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-14 00:00:00 -04:00
13
+ date: 2011-03-15 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -70,7 +70,6 @@ files:
70
70
  - lib/epitools/clitools.rb
71
71
  - lib/epitools/colored.rb
72
72
  - lib/epitools/hexdump.rb
73
- - lib/epitools/http.rb
74
73
  - lib/epitools/lcs.rb
75
74
  - lib/epitools/metaclass.rb
76
75
  - lib/epitools/niceprint.rb
@@ -1,82 +0,0 @@
1
- require 'net/http'
2
- require 'uri'
3
-
4
- # TODO: what?? this needs to be a class.
5
-
6
- class PartialPage < Exception
7
- attr_accessor :data
8
- end
9
-
10
- def read_data_from_response(response, amount)
11
-
12
- amount_read = 0
13
- chunks = []
14
-
15
- begin
16
- response.read_body do |chunk| # read body now
17
-
18
- amount_read += chunk.length
19
-
20
- if amount_read > amount
21
- amount_of_overflow = amount_read - amount
22
- chunk = chunk[0...-amount_of_overflow]
23
- end
24
-
25
- chunks << chunk
26
-
27
- if amount_read >= amount
28
- raise PartialPage.new chunks.join('')
29
- end
30
-
31
- end
32
- end
33
-
34
- end
35
-
36
-
37
- def http_get_streaming(url = URI.parse("http://epi.is-a-geek.net/files/Mr.%20Show%20-%20Civil%20War%20Re-enactment.avi"))
38
-
39
- #headers = {'User-Agent' => "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1"}
40
- headers = nil
41
-
42
- Net::HTTP.start(url.host, url.port) do |http|
43
- # using block
44
- response = http.request_get(url.path, headers) {|response|
45
- puts "Response: #{response.inspect}"
46
- puts "to hash: #{response.to_hash.inspect}"
47
-
48
- begin
49
- read_data_from_response(response, 500)
50
- rescue PartialPage => p
51
- puts "GOT THE PARTIAL PAGE!"
52
- data = p.data
53
- end
54
-
55
- puts
56
- puts "===========first 500 bytes================="
57
- puts data
58
- }
59
- end
60
-
61
- end
62
-
63
-
64
- # TODO: Remove RIO dependancy.
65
-
66
- def http_get_cached(url)
67
- require 'digest/md5'
68
- require 'rio'
69
-
70
- tempdir = ENV['TEMP']
71
- cachefile = rio(tempdir, "cached_url_#{Digest::SHA1.hexdigest(url)}")
72
-
73
- if cachefile.exist?
74
- data = rio(cachefile).read
75
- else
76
- data = rio(url).read
77
- rio(cachefile).binmode < data
78
- end
79
-
80
- data
81
- end
82
-