Refactor the Helper methods into methods on standard objects.

This commit is contained in:
Louis Mullie 2012-10-15 00:25:07 -04:00
parent 847ea450f6
commit 301c8692df
23 changed files with 60 additions and 219 deletions

View File

@ -26,7 +26,7 @@ module Treat::Core::Installer
def self.install(language = 'english')
# Require the Rubygem dependency installer.
Treat::Helpers::Verbosity.silence_warnings do
silence_warnings do
require 'rubygems/dependency_installer'
end

View File

@ -70,7 +70,7 @@ module Treat::Entities
def initialize(value = '', id = nil)
id ||= object_id; super(value, id)
@type = :entity if self == Entity
@type ||= ucc(cl(self.class)).intern
@type ||= self.class.mn.ucc.intern
end
# Add an entity to the current entity.
@ -124,7 +124,8 @@ module Treat::Entities
msg = Treat::Workers::Category.lookup(sym) ?
"Method #{sym} can't be called on a #{type}." :
"Method #{sym} is not defined by Treat." +
did_you_mean?(Treat::Workers.methods, sym)
Treat::Helpers::Help.did_you_mean?(
Treat::Workers.methods, sym)
raise Treat::Exception, msg
end

View File

@ -35,7 +35,7 @@ module Treat::Entities::Entity::Applicable
entity_types = group.targets
f = nil
entity_types.each do |t|
f = true if is_a?(Treat::Entities.const_get(cc(t)))
f = true if is_a?(Treat::Entities.const_get(t.cc))
end
if f || entity_types.include?(:entity)
send(task, worker, options)

View File

@ -71,9 +71,9 @@ module Treat::Entities::Entity::Buildable
end
e = anything_from_string(string)
if enforce_type && !e.is_a?(self)
raise "Asked to build a #{cl(self).downcase} "+
raise "Asked to build a #{self.mn.downcase} "+
"from \"#{string}\" and to enforce type, "+
"but type detected was #{cl(e.class).downcase}."
"but type detected was #{e.class.mn.downcase}."
end
e
end
@ -257,7 +257,7 @@ module Treat::Entities::Entity::Buildable
# Build any kind of entity from a string.
def anything_from_string(string)
case cl(self).downcase.intern
case self.mn.downcase.intern
when :document, :collection
raise Treat::Exception,
"Cannot create a document or " +

View File

@ -15,7 +15,7 @@ module Treat::Entities::Entity::Checkable
g2 = Treat::Workers::Category.lookup(feature)
raise Treat::Exception,
"#{g1.type.to_s.capitalize} #{task} " +
"#{g1.type.to_s.capitalize} " +
"requires #{g2.type} #{g2.method}."
end

View File

@ -7,7 +7,7 @@ module Treat::Entities::Entity::Comparable
def compare_with(klass)
i = 0; rank_a = nil; rank_b = nil
Treat.core.entities.order.each do |type|
klass2 = Treat::Entities.const_get(cc(type))
klass2 = Treat::Entities.const_get(type.cc)
rank_a = i if self <= klass2
rank_b = i if klass <= klass2
next if rank_a && rank_b

View File

@ -10,27 +10,25 @@ module Treat::Entities::Entity::Delegatable
return unless opt
self.class_eval do
group.presets.each do |preset|
define_method(preset) do |worker=nil, options={}|
return get(preset) if has?(preset)
options = {opt => preset}.merge(options)
m = group.method
send(m, worker, options)
f = unset(m)
features[preset] = f if f
group.presets.each do |preset|
define_method(preset) do |worker=nil, options={}|
return get(preset) if has?(preset)
options = {opt => preset}.merge(options)
m = group.method
send(m, worker, options)
f = unset(m)
features[preset] = f if f
end
end
end
end
end
# Add the workers to perform a task on an entity class.
def add_workers(group)
self.class_eval do
task = group.method
add_presets(group)
define_method(task) do |worker=nil, options={}|
if worker.is_a?(Hash)
options, worker =
@ -64,7 +62,7 @@ module Treat::Entities::Entity::Delegatable
worker_not_found(worker, group)
end
worker = group.const_get(cc(worker.to_s).intern)
worker = group.const_get(worker.to_s.cc.intern)
result = worker.send(group.method, entity, options)
if group.type == :annotator && result
@ -93,8 +91,7 @@ module Treat::Entities::Entity::Delegatable
lang = Treat.languages[language]
cat = group.to_s.split('::')[2].downcase.intern
group = ucc(cl(group)).intern
group = group.mn.ucc.intern
if lang.nil?
raise Treat::Exception,
"No configuration file loaded for language #{language}."
@ -121,9 +118,9 @@ module Treat::Entities::Entity::Delegatable
# Return an error message and suggest possible typos.
def worker_not_found(klass, group)
"Algorithm '#{ucc(cl(klass))}' couldn't be "+
"found in group #{group}." + did_you_mean?(
group.list.map { |c| ucc(c) }, ucc(klass))
"Algorithm '#{cl(klass).ucc}' couldn't be "+
"found in group #{group}." + Treat::Helpers::Help.
did_you_mean?(group.list.map { |c| c.ucc }, klass.ucc)
end
end

View File

@ -11,7 +11,7 @@ module Treat::Entities::Entity::Iterable
types = [:entity] if types.size == 0
f = false
types.each do |t2|
if is_a?(Treat::Entities.const_get(cc(t2)))
if is_a?(Treat::Entities.const_get(t2.cc))
f = true; break
end
end
@ -57,7 +57,7 @@ module Treat::Entities::Entity::Iterable
def ancestor_with_type(type)
return unless has_parent?
ancestor = @parent
type_klass = Treat::Entities.const_get(cc(type))
type_klass = Treat::Entities.const_get(type.cc)
while not ancestor.is_a?(type_klass)
return nil unless (ancestor && ancestor.has_parent?)
ancestor = ancestor.parent

View File

@ -34,7 +34,8 @@ module Treat::Entities::Entity::Stringable
# Return an informative string representation
# of the entity.
def inspect
s = "#{cl(self.class)} (#{@id.to_s})"
name = self.class.mn
s = "#{name} (#{@id.to_s})"
if caller_method(2) == :inspect
@id.to_s
else

View File

@ -1,57 +0,0 @@
# Search the list to see if there are
# words similar to #name in the #list
# If yes, return a string saying
# "Did you mean ... ?" with the names.
def did_you_mean?(list, name)
return '' # Fix
list = list.map { |e| e.to_s }
name = name.to_s
sugg = []
list.each do |element|
l = levenshtein(element,name)
if l > 0 && l < 2
sugg << element
end
end
unless sugg.size == 0
if sugg.size == 1
msg += " Perhaps you meant '#{sugg[0]}' ?"
else
sugg_quote = sugg[0..-2].map do
|x| '\'' + x + '\''
end
msg += " Perhaps you meant " +
"#{sugg_quote.join(', ')}," +
" or '#{sugg[-1]}' ?"
end
end
msg
end
alias :dym? :did_you_mean?
# Return the levensthein distance between
# two strings taking into account the costs
# of insertion, deletion, and substitution.
# Used by did_you_mean? to detect typos.
def levenshtein(first, other, ins=1, del=1, sub=1)
return nil if first.nil? || other.nil?
dm = []
dm[0] = (0..first.length).collect { |i| i * ins}
fill = [0] * (first.length - 1).abs
for i in 1..other.length
dm[i] = [i * del, fill.flatten]
end
for i in 1..other.length
for j in 1..first.length
dm[i][j] = [
dm[i-1][j-1] +
(first[i-1] ==
other[i-1] ? 0 : sub),
dm[i][j-1] + ins,
dm[i-1][j] + del
].min
end
end
dm[other.length][first.length]
end

View File

@ -1,15 +0,0 @@
# This is ugly, we should change it.
EscapeChar = '^^'
EscapedEscapeChar = '\^\^'
def escape_floats!(s)
s.gsub!(/([0-9]+)\.([0-9]+)/) do
$1 + EscapeChar + $2
end
end
def unescape_floats!(s)
s.gsub!(/([0-9]+)#{EscapedEscapeChar}([0-9]+)/) do
$1 + '.' + $2
end
end

View File

@ -1,41 +0,0 @@
# A cache to optimize camel casing.
@@cc_cache = {}
# A cache to optimize un camel casing.
@@ucc_cache = {}
# Convert un_camel_case to CamelCase.
def camel_case(o_phrase)
phrase = o_phrase.to_s.dup
return @@cc_cache[o_phrase] if @@cc_cache[o_phrase]
if Treat.core.acronyms.include?(phrase)
phrase = phrase.upcase
else
phrase.gsub!(/^[a-z]|_[a-z]/) { |a| a.upcase }
phrase.gsub!('_', '')
end
@@cc_cache[o_phrase] = phrase
end
alias :cc :camel_case
# Convert CamelCase to un_camel_case.
def un_camel_case(o_phrase)
phrase = o_phrase.to_s.dup
return @@ucc_cache[o_phrase] if @@ucc_cache[o_phrase]
if Treat.core.acronyms.include?(phrase.downcase)
phrase = phrase.downcase
else
phrase.gsub!(/[A-Z]/) { |p| '_' + p.downcase }
phrase = phrase[1..-1] if phrase[0] == '_'
end
@@ucc_cache[o_phrase] = phrase
end
alias :ucc :un_camel_case
# Retrieve the Class from a Module::Class.
def class_name(n); n.to_s.split('::')[-1]; end
alias :cl :class_name

View File

@ -1,8 +0,0 @@
def object_to_hash(obj)
hash = {}
obj.instance_variables.each do |var|
val = obj.instance_variable_get(var)
hash[var.to_s.delete("@")] = val
end
hash
end

View File

@ -1,27 +0,0 @@
# Require file utilities for creating and
# deleting temporary files.
require 'fileutils'
# Create a temporary file which is deleted
# after execution of the block.
def create_temp_file(ext, value = nil, &block)
fname = Treat.paths.tmp +
"#{Random.rand(10000000).to_s}.#{ext}"
File.open(fname, 'w') do |f|
f.write(value) if value
block.call(f.path)
end
ensure
File.delete(fname)
end
# Create a temporary directory, which is
# deleted after execution of the block.
def create_temp_dir(&block)
dname = Treat.paths.tmp +
"#{Random.rand(10000000).to_s}"
Dir.mkdir(dname)
block.call(dname)
ensure
FileUtils.rm_rf(dname)
end

View File

@ -1,19 +1,7 @@
# Runs a block of code without warnings.
def silence_warnings(&block)
warn_level = $VERBOSE
$VERBOSE = nil
result = block.call
$VERBOSE = warn_level
result
end
# Runs a block of code while blocking stdout.
def silence_stdout(log = '/dev/null')
unless Treat.core.verbosity.silence
yield; return
end
old = $stdout.dup
$stdout.reopen(File.new(log, 'w'))
yield
$stdout = old
end
# Handles the verbosity for external
# programs (gems, binaries, etc.)
module Treat::Helpers::Verbosity
end

View File

@ -28,7 +28,7 @@ class Treat::Workers::Formatters::Readers::Autoselect
format = default_to if format.to_s == ''
begin
Treat::Workers::Formatters::Readers.const_get(cc(format))
Treat::Workers::Formatters::Readers.const_get(format.cc)
rescue Treat::Exception
format = default_to
end

View File

@ -105,7 +105,7 @@ class Treat::Workers::Formatters::Unserializers::XML
end
def self.revive(type, value, id)
klass = Treat::Entities.const_get(cc(type))
klass = Treat::Entities.const_get(type.cc)
klass.new(value, id)
end

View File

@ -3,8 +3,8 @@ module Treat::Workers::Group
# Lazily load the worker classes in the group.
def const_missing(const)
bits = self.ancestors[0].to_s.split('::')
bits.collect! { |bit| ucc(bit) }
file = bits.join('/') + "/#{ucc(const)}"
bits.collect! { |bit| bit.ucc }
file = bits.join('/') + "/#{const.ucc}"
if not File.readable?(Treat.paths.lib + "#{file}.rb")
raise Treat::Exception,
"File '#{file}.rb' corresponding to " +
@ -26,7 +26,7 @@ module Treat::Workers::Group
# Populates once the list of the workers in the group
# by crawling the filesystem.
def list
mod = ucc(cl(self))
mod = self.mn.ucc
if @@list[mod].nil?
@@list[mod] = []
dirs = Dir[Treat.paths.lib + "treat/workers/*/#{mod}/*.rb"]
@ -43,7 +43,7 @@ module Treat::Workers::Group
def has_target?(target, strict = false)
is_target = false
self.targets.each do |entity_type|
t = cc(entity_type)
t = entity_type.cc
entity_type = Treat::Entities.const_get(t)
if target < entity_type ||
entity_type == target
@ -57,10 +57,10 @@ module Treat::Workers::Group
# the algorithm is added, it will be automatically
# installed on all the targets of the group.
def add(class_name, &block)
c = cc(class_name).intern
c = class_name.cc.intern
klass = self.const_set(c, Class.new)
method = self.method
@@list[ucc(cl(self))] << class_name
@@list[self.mn.ucc] << class_name
klass.send(:define_singleton_method,
method) do |entity, options={}|
block.call(entity, options)
@ -75,7 +75,7 @@ module Treat::Workers::Group
# Modify the extended class.
def self.extended(group)
group.module_eval do
class << self
@ -114,7 +114,7 @@ module Treat::Workers::Group
@method = nil
def self.method
return @method if @method
m = ucc(cl(self)).dup
m = self.mn.ucc.dup
if m[-4..-1] == 'zers'
if type == :annotator
m[-5..-1] = m[-6] == 'l' ? '' : 'y'

View File

@ -7,7 +7,7 @@ class Treat::Workers::Processors::Chunkers::Autoselect
end
begin
k = Treat::Workers::Processors::
Chunkers.const_get(cc(entity.format))
Chunkers.const_get(entity.format.cc)
k.chunk(entity, options)
rescue Treat::Exception
Treat::Workers::Processors::

View File

@ -36,12 +36,14 @@ class Treat::Workers::Processors::Segmenters::Punkt
lang = entity.language
set_options(lang, options)
s = entity.to_s
# Replace the point in all floating-point numbers
# by ^^; this is a fix since Punkt trips on decimal
# numbers.
escape_floats!(s)
s.escape_floats!
# Take out suspension points temporarily.
s.gsub!('...', '&;&.')
# Remove abbreviations.
@ -57,7 +59,7 @@ class Treat::Workers::Processors::Segmenters::Punkt
result.each do |sentence|
# Unescape the sentence.
unescape_floats!(sentence)
sentence.unescape_floats!
# Repair abbreviations in sentences.
sentence.gsub!('&-&', '.')
# Repair suspension points.

View File

@ -17,7 +17,7 @@ class Treat::Workers::Processors::Segmenters::SRX
lang = entity.language
entity.check_hasnt_children
text = entity.to_s
escape_floats!(text)
text.escape_floats!
unless @@segmenters[lang]
# Require the appropriate gem.
@ -30,7 +30,7 @@ class Treat::Workers::Processors::Segmenters::SRX
sentences = @@segmenters[lang].new(text)
sentences.each do |sentence|
unescape_floats!(sentence)
sentence.unescape_floats!
entity << Treat::Entities::Phrase.
from_string(sentence.strip)
end

View File

@ -26,13 +26,13 @@ class Treat::Workers::Processors::Segmenters::Tactful
entity.check_hasnt_children
s = entity.to_s
escape_floats!(s)
s.escape_floats!
# Remove abbreviations.
s.scan(/(?:[A-Za-z]\.){2,}/).each do |abbr|
s.gsub!(abbr, abbr.gsub(' ', '').gsub('.', '&-&'))
end
# Take out suspension points temporarily.
s.gsub!('...', '&;&.')
# Unstick sentences from each other.
@ -43,7 +43,7 @@ class Treat::Workers::Processors::Segmenters::Tactful
sentences = @@segmenter.tokenize_text(s)
sentences.each do |sentence|
unescape_floats!(sentence)
sentence.unescape_floats!
# Repair abbreviations.
sentence.gsub!('&-&', '.')
# Repair suspension points.

View File

@ -18,7 +18,7 @@ module Treat::Specs::Workers
def initialize(mode)
klass = self.class.const_get(:Scenarios)
@scenarios, @mode = klass, mode
@language = cl(self.class).downcase
@language = self.class.mn.downcase
end
end
end
@ -57,8 +57,8 @@ module Treat::Specs::Workers
category.members.each do |grp|
group = category[grp]
group_class = Treat::Workers.
const_get(cc(cat)).
const_get(cc(grp))
const_get(cat.cc).
const_get(grp.cc)
#next unless group_class ==
#Treat::Workers::Learners::Classifiers
group.each do |worker|
@ -178,7 +178,7 @@ module Treat::Specs::Workers
scenario[:examples], scenario[:generator],
scenario[:preprocessor]
target_class = Treat::Entities.
const_get(cc(target))
const_get(target.cc)
if examples.is_a?(Hash)
unless examples[worker]
raise Treat::Exception,
@ -246,7 +246,7 @@ module Treat::Specs::Workers
# the Ruby file defining the worker/adapter.
def get_worker_info(worker, group)
bits = group.to_s.split('::')
bits.collect! { |bit| ucc(bit) }
bits.collect! { |bit| bit.ucc }
file = bits.join('/') + "/#{worker}.rb"
contents = File.read(Treat.paths.lib + file)
head = contents[0...contents.index('class')]