Skip to content

Commit

Permalink
A whole bunch of changes, plus Ruby 2.0/1.8 compatability fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
epitron committed Feb 13, 2013
1 parent e6c1fa7 commit b2ac6a1
Show file tree
Hide file tree
Showing 15 changed files with 201 additions and 103 deletions.
5 changes: 3 additions & 2 deletions Guardfile
Expand Up @@ -10,7 +10,8 @@
guard :rspec, :version => 2, :cli => "--color", :bundler => false, :all_after_pass => false, :all_on_start => false, :keep_failed => false do
#guard 'rspec', :version => 2 do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/epitools/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
watch(%r{^lib/epitools/([^/]+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^lib/epitools/([^/]+)/.+\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
end

4 changes: 2 additions & 2 deletions README.rdoc
@@ -1,8 +1,8 @@
= epitools

Useful miscellaneous improvements for base Ruby objects, plus some extra
data structures and handy wrappers. (Think of it as a light-weight version
of ActiveSupport.
data structures and handy wrappers. You can think of it as a light-weight
ActiveSupport.

All epitools modules (and a bunch of Ruby's stdlib) are
{loaded on demand with "autoload"}[https://github.com/epitron/epitools/blob/master/lib/epitools/autoloads.rb],
Expand Down
6 changes: 3 additions & 3 deletions Rakefile
@@ -1,13 +1,13 @@
VERSION = File.read("VERSION").strip
gem_version = File.read("VERSION").strip

task :build do
system "gem build .gemspec"
end

task :release => :build do
system "gem push epitools-#{VERSION}.gem"
system "gem push epitools-#{gem_version}.gem"
end

task :install => :build do
system "gem install epitools-#{VERSION}.gem"
system "gem install epitools-#{gem_version}.gem"
end
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
0.5.19
0.5.20
44 changes: 31 additions & 13 deletions lib/epitools/autoloads.rb
@@ -1,9 +1,9 @@
## Standard library

autoload :Set, 'set'
autoload :URI, 'uri'
autoload :CGI, 'cgi'
autoload :Base64, 'base64'
autoload :JSON, 'json'
autoload :Zlib, 'zlib'
autoload :FileUtils, 'fileutils'
autoload :Tempfile, 'tempfile'
Expand All @@ -18,28 +18,22 @@
autoload :Benchmark, 'benchmark'
autoload :Tracer, 'tracer'
autoload :CSV, 'csv'
#autoload :DelegateClass, 'delegate'

# YAML is sometimes loaded improperly.
if defined? YAML and not defined? YAML.parse
del YAML # remove the existing module
module Digest
autoload :SHA1, 'digest/sha1'
autoload :SHA2, 'digest/sha2'
autoload :MD5, 'digest/md5'
end

autoload :YAML, 'yaml'

if RUBY_VERSION["1.8.7"]
autoload :Prime, 'mathn'
else
autoload :Prime, 'prime'
end

module Digest
autoload :SHA1, 'digest/sha1'
autoload :SHA2, 'digest/sha2'
autoload :MD5, 'digest/md5'
end

## Nonstandard library
## Nonstandard library (epitools)

autoload :Path, 'epitools/path'
autoload :Ezdb, 'epitools/ezdb'
autoload :Browser, 'epitools/browser'
Expand All @@ -54,7 +48,31 @@ module Digest
autoload :TypedStruct, 'epitools/typed_struct'
autoload :Sys, 'epitools/sys'


## Gems (common)

autoreq :Nokogiri, 'nokogiri'
autoreq :ANSI, 'ansi'
autoreq :BSON, 'bson'
autoreq :JSON, 'json'


## Network stuff

# Sockets
['IP', 'Basic', 'TCP', 'UDP', 'UNIX', ''].each do |type|
autoload :"#{type}Socket", 'socket'
end

# Servers
['TCP', 'UNIX'].each do |type|
autoload :"#{type}Server", 'socket'
end


## YAML hacks (sometimes the module is loaded improperly)

if defined? YAML and not defined? YAML.parse
del YAML # remove the existing module
end
autoreq :YAML, 'yaml'
19 changes: 13 additions & 6 deletions lib/epitools/core_ext/array.rb
Expand Up @@ -66,7 +66,7 @@ def ^(other)
#
# Shuffle the array
#
unless defined? shuffle
unless instance_methods.include? :shuffle
def shuffle
sort_by{rand}
end
Expand All @@ -75,13 +75,20 @@ def shuffle
#
# Pick (a) random element(s).
#
unless defined? sample
unless instance_methods.include? :sample
def sample(n=1)
if n == 1
self[rand(size)]
else
shuffle[0...n]
return self[rand sz] if n == 1

sz = size
indices = []

loop do
indices += (0..n*1.2).map { rand sz }
indices.uniq
break if indices.size >= n
end

values_at(*indices[0...n])
end
end
alias_method :pick, :sample
Expand Down
84 changes: 59 additions & 25 deletions lib/epitools/core_ext/enumerable.rb
Expand Up @@ -35,7 +35,7 @@ def skip(n)
end
end
else
enum_for :skip, n
to_enum(:skip, n)
end
end

Expand Down Expand Up @@ -166,16 +166,22 @@ def average
# Example:
# [ [1,2], [3,4] ].deep_map{|e| e ** 2 } #=> [ [1,4], [9,16] ]
#
def deep_map(depth=nil, &block)
map do |obj|
def deep_map(max_depth=nil, current_depth=0, parent=nil, &block)
return self if max_depth and (current_depth > max_depth)

case obj
when Enumerable
obj.deep_map(&block)
map do |obj|
if obj == parent # infinite loop scenario!
yield obj
else
block.call(obj)
case obj
when String
yield obj
when Enumerable
obj.deep_map(max_depth, current_depth+1, self, &block)
else
yield obj
end
end

end
end

Expand All @@ -190,30 +196,58 @@ def deep_map(depth=nil, &block)
# Example:
# [ [1,2], [3,4] ].deep_select{|e| e % 2 == 0 } #=> [ [2], [4] ]
#
def deep_select(depth=nil, &block)
map do |*args|

obj = args.last

if depth.nil? or depth > 0
def deep_select(max_depth=nil, current_depth=0, parent=nil, &block)
return self if max_depth and (current_depth > max_depth)

map do |obj|
p [:obj, obj]
result = if obj == parent # infinite loop scenario!
p :infinite
obj if yield obj
else
case obj
when Hash

when Array, Enumerable
result = obj.deep_select(depth ? depth-1 : nil, &block)
result.any? ? result : nil
when String
p :string
obj if yield obj
when Enumerable
p :recurse
obj.deep_select(max_depth, current_depth+1, self, &block)
else
p :else
p [:yield, yield(obj)]
obj if yield obj
end

else
obj if block.call(obj)
end

p [:result, result]
result
end.compact
end

alias_method :recursive_select, :deep_select
# def deep_select(depth=nil, &block)
# map do |*args|

# obj = args.last

# if depth.nil? or depth > 0

# case obj
# when Hash

# when Array, Enumerable
# result = obj.deep_select(depth ? depth-1 : nil, &block)
# result.any? ? result : nil
# end

# else
# obj if block.call(obj)
# end

# end.compact
# end

alias_method :recursive_select, :deep_select
alias_method :select_recursively, :deep_select
alias_method :select_recursive, :deep_select

#
# Identical to "reduce" in ruby1.9 (or foldl in haskell.)
Expand Down Expand Up @@ -324,7 +358,7 @@ class Enumerator
# Display a spinner every `every` elements that pass through the Enumerator.
#
def with_spinner(every=37)
Enumerator.new do |yielder|
to_enum do |yielder|
spins = 0

each.with_index do |e, i|
Expand Down
14 changes: 11 additions & 3 deletions lib/epitools/core_ext/misc.rb
Expand Up @@ -9,6 +9,7 @@ def to_hash

end


class Binding

#
Expand All @@ -30,15 +31,22 @@ def []=(key, val)
#
# Return all the local variables in the binding
#
def local_variables
eval("local_variables")

if RUBY_VERSION["1.8"]
def local_variables
eval("local_variables").map(&:to_sym)
end
else
def local_variables
eval("local_variables")
end
end

alias_method :keys, :local_variables

end



class Proc

#
Expand Down
15 changes: 11 additions & 4 deletions lib/epitools/core_ext/numbers.rb
Expand Up @@ -19,8 +19,12 @@ def commatize
def clamp(range)
if self < range.first
range.first
elsif self > range.last
range.last
elsif self >= range.last
if range.exclude_end?
range.last - 1
else
range.last
end
else
self
end
Expand Down Expand Up @@ -95,8 +99,11 @@ def #{meth}

end

def log(n)
Math.log(self, n)
# Math.log is different in 1.8
if RUBY_VERSION["1.8"]
def log(n); Math.log(self) / Math.log(n); end
else
def log(n); Math.log(self, n); end
end


Expand Down
4 changes: 3 additions & 1 deletion lib/epitools/core_ext/string.rb
@@ -1,3 +1,4 @@
require 'epitools/minimal'
require 'epitools/core_ext/numbers'

class String
Expand Down Expand Up @@ -107,6 +108,7 @@ def urldecode
# Convert a query string to a hash of params
#
def to_params
require 'cgi' unless defined? CGI.parse
CGI.parse(self).map_values do |v|
# CGI.parse wraps every value in an array. Unwrap them!
if v.is_a?(Array) and v.size == 1
Expand Down Expand Up @@ -231,7 +233,7 @@ def from_json
# Parse this string as YAML
#
def from_yaml
YAML.parse(self).to_ruby
YAML.load(self)
end

#
Expand Down
10 changes: 1 addition & 9 deletions lib/epitools/minimal.rb
Expand Up @@ -4,14 +4,6 @@
Enumerator = Enumerable::Enumerator unless defined? Enumerator
end

unless defined? Enum
if defined? Enumerator
Enum = Enumerator
else
$stderr.puts "WARNING: Couldn't find the Enumerator class. Enum will not be available."
end
end

RbConfig = Config unless defined? RbConfig


Expand Down Expand Up @@ -121,7 +113,7 @@ def self.enumerable *meths
alias_method "#{meth}_without_enumerator", meth
class_eval %{
def #{meth}(*args, &block)
return Enum.new(self, #{meth.inspect}, *args, &block) unless block_given?
return to_enum(#{meth.inspect}, *args, &block) unless block_given?
#{meth}_without_enumerator(*args, &block)
end
}
Expand Down
2 changes: 1 addition & 1 deletion lib/epitools/rash.rb
Expand Up @@ -51,7 +51,7 @@ def [](key)
# Return everything that matches the query.
#
def all(query)
return Enumerator.new(self, :all, query) unless block_given?
return to_enum(:all, query) unless block_given?

if @hash.include? query
yield @hash[query]
Expand Down

0 comments on commit b2ac6a1

Please sign in to comment.