Module: Splib

Defined in:
lib/splib.rb,
lib/splib/Exec.rb,
lib/splib/Array.rb,
lib/splib/Float.rb,
lib/splib/Sleep.rb,
lib/splib/Monitor.rb,
lib/splib/Constants.rb,
lib/splib/Conversions.rb,
lib/splib/CodeReloader.rb,
lib/splib/PriorityQueue.rb,
lib/splib/UrlShorteners.rb,
lib/splib/HumanIdealRandomIterator.rb

Defined Under Namespace

Classes: Complete, EmptyQueue, IdealHumanRandomIterator, Monitor, PriorityQueue, Wakeup

Constant Summary collapse

LIBS =
[:Array,
 :CodeReloader,
 :Constants,
 :Conversions,
 :Exec,
 :Float,
 :HumanIdealRandomIterator,
 :Monitor,
 :PriorityQueue,
 :Sleep,
 :UrlShorteners
]
Suff =
bytes

number of bytes

Converts bytes into easy human readable form O(1) version by Ryan “pizza_milkshake” Flynn

[
"",       # 1024^0
"Kilo",   # 1024^1
"Mega",   # 1024^2
"Giga",   # 1024^3
"Tera",   # 1024^4
"Peta",   # 1024^5
"Exa",    # 1024^6
"Zetta",  # 1024^7
"Yotta"   # 1024^8
]
@@processes =
[]

Class Method Summary collapse

Class Method Details

.create_holder(path) ⇒ Object

path

path to ruby code

Creates a module to hold loaded code



51
52
53
54
55
56
57
58
# File 'lib/splib/CodeReloader.rb', line 51

def self.create_holder(path)
    return Module.new do
        @path = path
        def self.path
            @path
        end
    end
end

.discover_constants(path, type = nil) ⇒ Object

path

path to ruby file

type

return constants only of given type

Find all constants in a given ruby file. Array of symbols is returned

Raises:

  • (ArgumentError)


14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/splib/CodeReloader.rb', line 14

def self.discover_constants(path, type=nil)
    raise ArgumentError.new('Failed to locate plugin file') unless File.exists?(path)
    consts = []
    sandbox = Module.new
    sandbox.module_eval(self.read_file(path))
    sandbox.constants.each do |const|
        klass = sandbox.const_get(const)
        if(type.nil? || (type && klass < type))
            sklass = klass.to_s.slice(klass.to_s.rindex(':')+1, klass.to_s.length)
            consts << sklass.to_sym
        end
    end
    return consts
end

.exec(*args) ⇒ Object

command

command string to execute

timeout

length of time to execute

maxbytes

maximum number return bytes allowed

Execute system command. This is a wrapper method that will redirect to the proper command



22
23
24
25
26
27
28
# File 'lib/splib/Exec.rb', line 22

def self.exec(*args)
    if(RUBY_PLATFORM == 'java')
        thread_exec(*args)
    else
        standard_exec(*args)
    end
end

.find_const(c, things = []) ⇒ Object

c

constant name (String)

things

Array of Object/Module constants to look in

Finds a constant if it exists

Example

Foo::Bar

Returns nil if nothing found

Raises:

  • (ArgumentError)


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/splib/Constants.rb', line 7

def self.find_const(c, things=[])
    raise ArgumentError.new('Exepcting an array') unless things.is_a?(Array)
    const = nil
    (things + [Object]).each do |base|
        begin
            c.split('::').each do |part|
                const = const.nil? ? base.const_get(part) : const.const_get(part)
            end
        rescue NameError
            const = nil
        end
        break unless const.nil?
    end
    const
end

.format_seconds(secs) ⇒ Object

secs

number of seconds

Converts seconds into a human readable string (This is an estimate and does not account for leaps)



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/splib/Conversions.rb', line 5

def self.format_seconds(secs)
    arg = [{:year => 31536000},
            {:month => 2678400},
            {:week => 604800},
            {:day => 86400},
            {:hour => 3600},
            {:minute => 60},
            {:second => 1}]
    res = ''
    arg.each do |val|
        val.each_pair do |k,v|
            z = (secs / v).to_i
            next unless z > 0
            res += " #{z} #{k}#{z == 1 ? '':'s'}"
            secs = secs % v
        end
    end
    res = '0 seconds' if res.empty?
    return res.strip
end

.format_size(bytes) ⇒ Object



40
41
42
43
44
45
46
# File 'lib/splib/Conversions.rb', line 40

def self.format_size(bytes)
    return "0 bytes" if bytes == 0
    mag = (Math.log(bytes) / Math.log(1024)).floor
    mag = [ Suff.length - 1, mag ].min
    val = bytes.to_f / (1024 ** mag)
    ("%.2f %sbyte%s" % [ val, Suff[mag], val == 1 ? "" : "s" ]).strip
end

.isgd_url(url) ⇒ Object

url

URL to shorten

Gets a is.gd for given URL



26
27
28
29
30
31
32
33
# File 'lib/splib/UrlShorteners.rb', line 26

def self.isgd_url(url)
    connection = Net::HTTP.new('is.gd', 80)
    resp, data = connection.get("/api.php?longurl=#{url}")
    if(resp.code !~ /^200$/)
        raise "Failed to make the URL small."
    end
    return data.strip
end

.load(*args) ⇒ Object

args

name of library to load

Loads the given library. Currently available: :CodeReloader :Constants :Conversions :Exec :HumanIdealRandomIterator :PriorityQueue :UrlShorteners :all



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/splib.rb', line 24

def self.load(*args)
    if(args.include?(:all))
        LIBS.each do |lib|
            require "splib/#{lib}"
        end
    else
        args.each do |lib|
            raise NameError.new("Unknown library name: #{lib}") unless LIBS.include?(lib)
            require "splib/#{lib}"
        end
    end
end

.load_code(path, holder = nil) ⇒ Object

path

path to ruby file

holder

module holding loaded ruby code

Load code from a ruby file into a module



32
33
34
35
36
37
38
39
40
# File 'lib/splib/CodeReloader.rb', line 32

def self.load_code(path, holder=nil)
    if(holder)
        raise ArgumentError.new('Expecting a module containing loaded code') unless holder.respond_to?(:path)
    else
        holder = self.create_holder(path)
    end
    holder.module_eval(self.read_file(path))
    holder
end

.read_file(path) ⇒ Object

path

path to file

Read contents of file



4
5
6
7
8
9
# File 'lib/splib/CodeReloader.rb', line 4

def self.read_file(path)
    file = File.open(path, 'rb')
    cont = file.read
    file.close
    cont
end

.reload_code(holder) ⇒ Object

holder

module holding loaded ruby code

Reload the code within the module

Raises:

  • (ArgumentError)


44
45
46
47
# File 'lib/splib/CodeReloader.rb', line 44

def self.reload_code(holder)
    raise ArgumentError.new('Expecting a module containing loaded code') unless holder.respond_to?(:path)
    self.load_code(holder.path)
end

.running_procsObject

Returns current array of running Processes



14
15
16
# File 'lib/splib/Exec.rb', line 14

def self.running_procs
    @@processes
end

.shortest_url(url) ⇒ Object

url

URL to shorten

Get shortest for given url



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/splib/UrlShorteners.rb', line 36

def self.shortest_url(url)
    results = []
    [:tiny_url, :isgd_url, :trim_url].each do |service|
        begin
            results << self.send(service, url)
        rescue
            #ignore#
        end
    end
    raise 'Failed to make URL small' if results.empty?
    results.sort{|a,b| a.length <=> b.length}[0]
end

.sleep(secs = nil) ⇒ Object

secs

Number of seconds to sleep (Use float to provide better actual sleep time)



4
5
6
7
8
# File 'lib/splib/Sleep.rb', line 4

def sleep(secs=nil)
    start = Time.now.to_f
    secs.nil? ? Kernel.sleep : Kernel.sleep(secs)
    Time.now.to_f - start
end

.standard_exec(command, timeout = 10, maxbytes = 500, priority = nil) ⇒ Object

command

command to execute

timeout

maximum number of seconds to run

maxbytes

maximum number of result bytes to accept

priority

set priority of the process

Execute a system command (use with care) This is the normal exec command that is used



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
# File 'lib/splib/Exec.rb', line 36

def self.standard_exec(command, timeout=10, maxbytes=500, priority=nil)
    timeout = timeout.to_i
    maxbytes = maxbytes.to_i
    priority = priority.to_i
    output = []
    pro = nil
    begin
        if(timeout > 0)
            Timeout::timeout(timeout) do
                pro = IO.popen(command)
                @@processes << pro
                if(priority > 0)
                    Process.setpriority(Process::PRIO_PROCESS, pro.pid, priority)
                end
                until(pro.closed? || pro.eof?)
                    output << pro.getc.chr
                    if(maxbytes > 0 && output.size > maxbytes)
                        raise IOError.new("Maximum allowed output bytes exceeded. (#{maxbytes} bytes)")
                    end
                end
            end
        else
            pro = IO.popen(command)
            @@processes << pro
            until(pro.closed? || pro.eof?)
                output << pro.getc.chr
                if(maxbytes > 0 && output.size > maxbytes)
                    raise IOError.new("Maximum allowed output bytes exceeded. (#{maxbytes} bytes)")
                end
            end
        end
        output = output.join('')
    ensure
        Process.kill('KILL', pro.pid) if Process.waitpid2(pro.pid, Process::WNOHANG).nil? # make sure the process is dead
        @@processes.delete(pro)
    end
    return output
end

.thread_exec(command, timeout = 10, maxbytes = 500) ⇒ Object

command

command to execute

timeout

maximum number of seconds to run

maxbytes

maximum number of result bytes to accept

priority

set priority of the process

Execute a system command (use with care) This is the threaded exec command that is generally used with JRuby. The regular timeout does not work when executing a process, so we do it in a separate thread and sleep the main thread until the timeout is reached.



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
# File 'lib/splib/Exec.rb', line 87

def self.thread_exec(command, timeout=10, maxbytes=500)
    timeout = timeout.to_i
    maxbytes = maxbytes.to_i
    priority = priority.to_i
    current = Thread.current
    output = []
    pro = nil
    thread = Thread.new do
        boom = Complete.new
        begin
            pro = IO.popen(command)
            @@processes << pro
            if(priority > 0)
                Process.setpriority(Process::PRIO_PROCESS, pro.pid, priority)
            end
            until(pro.closed? || pro.eof?)
                output << pro.getc.chr
                if(maxbytes > 0 && output.size > maxbytes)
                    raise IOError.new("Maximum allowed output bytes exceeded. (#{maxbytes} bytes)")
                end
            end
        rescue Exception => boom
            # just want it set
        end
        current.raise boom unless boom.is_a?(Timeout::Error)
    end
    begin
        begin
            if(timeout > 0)
                thread.join(timeout)
                thread.raise Timeout::Error.new
                raise Timeout::Error.new
            else
                thread.join
            end
            output.join('')
        rescue Complete
            # ignore this exception
        end
    ensure
        Process.kill('KILL', pro.pid) unless pro.nil?
        @@processes.delete(pro)
    end
    output.join('')
end

.tiny_url(url) ⇒ Object

url

URL to shorten

Gets a tinyurl for given URL



6
7
8
9
10
11
12
13
# File 'lib/splib/UrlShorteners.rb', line 6

def self.tiny_url(url)
    connection = Net::HTTP.new('tinyurl.com', 80)
    resp, data = connection.get("/api-create.php?url=#{url}")
    if(resp.code !~ /^200$/)
        raise "Failed to make the URL small."
    end
    return data.strip
end

.trim_url(url) ⇒ Object

url

URL to shorten

Gets a tr.im for given URL



16
17
18
19
20
21
22
23
# File 'lib/splib/UrlShorteners.rb', line 16

def self.trim_url(url)
    connection = Net::HTTP.new('api.tr.im', 80)
    resp, data = connection.get("/v1/trim_simple?url=#{url}")
    if(resp.code !~ /^200$/)
        raise "Failed to make the URL small."
    end
    return data.strip
end

.type_of?(a, b) ⇒ Boolean

a

an object

b

constant or string

Returns true of a is a type of b. b can be given as a String to allow for matching of types contained within a module or for types that may not be loaded

Returns:

  • (Boolean)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/splib/Constants.rb', line 28

def self.type_of?(a, b)
    case b
    when String
        if(a.class.to_s.slice(0).chr == '#')
            name = a.class.to_s
            return name.slice(name.index('::')+2, name.length) == b
        else
            const = self.find_const(b)
            return const.nil? ? false : a.is_a?(const)
        end
    when Class
        return a.is_a?(b)
    else
        raise ArgumentError.new('Comparision type must be a string or constant')
    end
end