intermine 0.99.03 → 1.00.00
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.
- data/Rakefile +39 -25
- data/lib/intermine/lists.rb +56 -20
- data/lib/intermine/model.rb +15 -102
- data/lib/intermine/query.rb +29 -58
- data/lib/intermine/results.rb +12 -27
- data/lib/intermine/service.rb +1 -0
- data/lib/intermine/version.rb +4 -6
- data/test/live_results.rb +164 -0
- data/test/live_summary_test.rb +59 -0
- data/test/live_test.rb +15 -20
- data/test/test_query.rb +22 -6
- data/test/test_result_row.rb +0 -30
- data/test/test_sugar.rb +14 -13
- metadata +8 -7
- data/TODO +0 -3
data/Rakefile
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
2
|
require 'rubygems/specification' unless defined?(Gem::Specification)
|
|
3
|
+
require 'rubygems/package_task'
|
|
3
4
|
require 'rake/testtask'
|
|
4
|
-
require 'rake/gempackagetask'
|
|
5
5
|
|
|
6
|
-
gem 'rdoc', '=2.1.0'
|
|
7
|
-
require 'rdoc/rdoc'
|
|
8
|
-
require 'rake/rdoctask'
|
|
9
|
-
|
|
10
|
-
gem 'darkfish-rdoc'
|
|
11
|
-
require 'darkfish-rdoc'
|
|
6
|
+
#gem 'rdoc'# , '=2.1.0'
|
|
7
|
+
#require 'rdoc/rdoc'
|
|
8
|
+
#require 'rake/rdoctask'
|
|
9
|
+
#
|
|
10
|
+
#gem 'darkfish-rdoc'
|
|
11
|
+
#require 'darkfish-rdoc'
|
|
12
12
|
|
|
13
13
|
def gemspec
|
|
14
14
|
@gemspec ||= begin
|
|
@@ -38,30 +38,44 @@ task :release => :package do
|
|
|
38
38
|
sh "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
Gem::PackageTask.new(gemspec) do |pkg|
|
|
42
42
|
pkg.need_zip = true
|
|
43
43
|
pkg.need_tar = true
|
|
44
|
-
|
|
45
44
|
end
|
|
46
45
|
|
|
47
|
-
Rake::TestTask.new do |t|
|
|
48
|
-
t.libs << "test"
|
|
49
|
-
t.test_files = FileList['test/unit_tests.rb']
|
|
50
|
-
t.verbose = true
|
|
51
|
-
end
|
|
52
46
|
|
|
53
|
-
Rake::TestTask.new(:live_tests) do |t|
|
|
54
|
-
t.libs << "test"
|
|
55
|
-
t.test_files = FileList['test/live_test.rb'] << FileList['test/live_summary_test.rb'] << FileList['test/live_results.rb']
|
|
56
|
-
t.verbose = true
|
|
57
|
-
end
|
|
58
47
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
48
|
+
namespace :test do
|
|
49
|
+
|
|
50
|
+
desc "Run the unit-tests"
|
|
51
|
+
Rake::TestTask.new(:unit) do |t|
|
|
52
|
+
t.libs << "test"
|
|
53
|
+
t.test_files = FileList['test/unit_tests.rb']
|
|
54
|
+
t.verbose = true
|
|
55
|
+
puts "Running UNIT TESTS"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
desc "Run the live integration tests"
|
|
59
|
+
Rake::TestTask.new(:live) do |t|
|
|
60
|
+
t.libs << "test"
|
|
61
|
+
t.test_files = FileList['test/live_test.rb'] << FileList['test/live_summary_test.rb'] << FileList['test/live_results.rb']
|
|
62
|
+
t.verbose = false
|
|
63
|
+
puts "Running LIVE INTEGRATION TESTS"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
desc "Run all tests"
|
|
67
|
+
task :all => [:unit, :live]
|
|
65
68
|
end
|
|
66
69
|
|
|
70
|
+
desc "Run the default test-suite"
|
|
71
|
+
task :test => ["test:all"]
|
|
72
|
+
|
|
73
|
+
#Rake::RDocTask.new do |t|
|
|
74
|
+
# t.title = 'InterMine Webservice Client Documentation'
|
|
75
|
+
# t.rdoc_files.include 'README.rdoc'
|
|
76
|
+
# t.rdoc_files.include 'lib/**/*rb'
|
|
77
|
+
# t.main = 'README.rdoc'
|
|
78
|
+
# t.options += ['-SHN', '-f', 'darkfish']
|
|
79
|
+
#end
|
|
80
|
+
|
|
67
81
|
|
data/lib/intermine/lists.rb
CHANGED
|
@@ -312,6 +312,54 @@ module InterMine::Lists
|
|
|
312
312
|
@tags = @manager.tags_for(self)
|
|
313
313
|
end
|
|
314
314
|
|
|
315
|
+
ENRICHMENT_DEFAULTS = {:correction => "Holm-Bonferroni", :maxp => 0.05}
|
|
316
|
+
|
|
317
|
+
# Retrieve the results of an enrichment calculation
|
|
318
|
+
#
|
|
319
|
+
# Get the results of an enrichment calculate_enrichment with the default parameter values:
|
|
320
|
+
#
|
|
321
|
+
# calculate_enrichment(widget)
|
|
322
|
+
#
|
|
323
|
+
# Pass optional parameters to the enrichment service:
|
|
324
|
+
#
|
|
325
|
+
# calculate_enrichment(widget, :correction => "Benjamini-Hochberg", :maxp => 0.1)
|
|
326
|
+
#
|
|
327
|
+
# The optional parameters are: :correction, :maxp, :filter
|
|
328
|
+
#
|
|
329
|
+
# Each result returned by the enrichment service is a hash with the following
|
|
330
|
+
# keys: "p-value", "identifier", "matches", "description". The Hash returned also allows
|
|
331
|
+
# key access with symbols.
|
|
332
|
+
#
|
|
333
|
+
def calculate_enrichment(widget, opts = {})
|
|
334
|
+
s = @manager.service
|
|
335
|
+
params = s.params.merge(ENRICHMENT_DEFAULTS).merge(opts).merge(:widget => widget, :list => @name)
|
|
336
|
+
uri = URI.parse(s.root + Service::LIST_ENRICHMENT_PATH)
|
|
337
|
+
res = Net::HTTP.post_form(uri, params)
|
|
338
|
+
return case res
|
|
339
|
+
when Net::HTTPSuccess
|
|
340
|
+
JSON.parse(res.body)["results"].map {|row| SymbolAcceptingHash[row] }
|
|
341
|
+
else
|
|
342
|
+
begin
|
|
343
|
+
container = JSON.parse(res.body)
|
|
344
|
+
raise ServiceError, container["error"]
|
|
345
|
+
rescue
|
|
346
|
+
res.error!
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
class SymbolAcceptingHash < Hash
|
|
352
|
+
|
|
353
|
+
def [](key)
|
|
354
|
+
return case key
|
|
355
|
+
when Symbol
|
|
356
|
+
return super(key.to_s.gsub(/[_]/, '-'))
|
|
357
|
+
else
|
|
358
|
+
return super(key)
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
315
363
|
private
|
|
316
364
|
|
|
317
365
|
# Used to interpret arguments to add and remove
|
|
@@ -675,10 +723,13 @@ module InterMine::Lists
|
|
|
675
723
|
def make_list_names(objs)
|
|
676
724
|
current_names = list_names
|
|
677
725
|
return objs.map do |x|
|
|
678
|
-
case
|
|
679
|
-
when
|
|
680
|
-
|
|
681
|
-
when
|
|
726
|
+
case x
|
|
727
|
+
when List
|
|
728
|
+
x.name
|
|
729
|
+
when x.respond_to?(:list_upload_uri)
|
|
730
|
+
create_list(x).name
|
|
731
|
+
when current_names.include?(x.to_s)
|
|
732
|
+
x.to_s
|
|
682
733
|
else
|
|
683
734
|
raise ArgumentError, "#{x} is not a list you can access"
|
|
684
735
|
end
|
|
@@ -708,17 +759,15 @@ module InterMine::Lists
|
|
|
708
759
|
else
|
|
709
760
|
begin
|
|
710
761
|
container = JSON.parse(response.body)
|
|
711
|
-
|
|
762
|
+
raise ServiceError, container["error"]
|
|
712
763
|
rescue
|
|
713
764
|
response.error!
|
|
714
765
|
end
|
|
715
|
-
raise ServiceError, container["error"]
|
|
716
766
|
end
|
|
717
767
|
end
|
|
718
768
|
|
|
719
769
|
# Routine for creating a list from a PathQuery::Query
|
|
720
770
|
def create_list_from_query(query, tags=[], name=nil, description=nil)
|
|
721
|
-
query = get_listable_query(query)
|
|
722
771
|
uri = query.list_upload_uri
|
|
723
772
|
list_params = {
|
|
724
773
|
"listName" => name,
|
|
@@ -730,19 +779,6 @@ module InterMine::Lists
|
|
|
730
779
|
return Net::HTTP.post_form(URI.parse(uri), params)
|
|
731
780
|
end
|
|
732
781
|
|
|
733
|
-
def get_listable_query(query)
|
|
734
|
-
clone = query.clone()
|
|
735
|
-
views = clone.views
|
|
736
|
-
selected_classes = views.map {|x| x.prefix}.uniq {|p| p.to_s}
|
|
737
|
-
if selected_classes.size == 1
|
|
738
|
-
return clone.select(selected_classes.first.append("id"))
|
|
739
|
-
elsif selected_classes.size == 0
|
|
740
|
-
return clone.select("#{clone.root.name}.id")
|
|
741
|
-
end
|
|
742
|
-
# Bound to fail, but let the service provide the message.
|
|
743
|
-
return clone
|
|
744
|
-
end
|
|
745
|
-
|
|
746
782
|
# Routine for creating a List in a webservice from a list of Ids.
|
|
747
783
|
def create_list_from_ids(ids, type, tags=[], name=nil, description=nil)
|
|
748
784
|
if @service.model.get_cd(type).nil?
|
data/lib/intermine/model.rb
CHANGED
|
@@ -402,46 +402,6 @@ module Metadata
|
|
|
402
402
|
return q
|
|
403
403
|
end
|
|
404
404
|
|
|
405
|
-
# call-seq:
|
|
406
|
-
# find(*attributes) => Enumerable[InterMineObject]
|
|
407
|
-
#
|
|
408
|
-
# Get the items in the database matching the identifiers.
|
|
409
|
-
#
|
|
410
|
-
# zen = model.table("Gene").find("zen")
|
|
411
|
-
# puts zen.length, zen.organism.name
|
|
412
|
-
#
|
|
413
|
-
# find may retrun multiple results:
|
|
414
|
-
#
|
|
415
|
-
# genes = model.table("Gene").find("zen", "eve", "r", "h")
|
|
416
|
-
#
|
|
417
|
-
# The search mechanism used is a "lookup" constraint, so extra-values
|
|
418
|
-
# may be provided to distinguish search terms by passing key-value pairs:
|
|
419
|
-
#
|
|
420
|
-
# starting_with_c = model.table("Gene").find("c*" => "D. melanogaster")
|
|
421
|
-
#
|
|
422
|
-
def find(*attrs)
|
|
423
|
-
q = new_query
|
|
424
|
-
q.select("*")
|
|
425
|
-
attrs.each do |attr|
|
|
426
|
-
if attr.is_a? Hash
|
|
427
|
-
attr.each do |term, extra|
|
|
428
|
-
q.or(@root, "LOOKUP", term, extra)
|
|
429
|
-
end
|
|
430
|
-
else
|
|
431
|
-
q.or(@root, "LOOKUP", attr)
|
|
432
|
-
end
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
c = q.count()
|
|
436
|
-
if c < 1
|
|
437
|
-
raise ItemNotFoundError
|
|
438
|
-
elsif c == 1
|
|
439
|
-
return q.results.first
|
|
440
|
-
else
|
|
441
|
-
return q.results
|
|
442
|
-
end
|
|
443
|
-
end
|
|
444
|
-
|
|
445
405
|
# call-seq:
|
|
446
406
|
# where(*constraints) => PathQuery::Query
|
|
447
407
|
#
|
|
@@ -487,8 +447,13 @@ module Metadata
|
|
|
487
447
|
# attributes (ie. columns that can hold values, rather than references to
|
|
488
448
|
# other tables.)
|
|
489
449
|
#
|
|
450
|
+
# The array returned will be sorted in alphabetical order by field-name.
|
|
451
|
+
#
|
|
490
452
|
def attributes
|
|
491
|
-
return @fields.
|
|
453
|
+
return @fields.
|
|
454
|
+
select {|_, v| v.is_a?(AttributeDescriptor)}.
|
|
455
|
+
sort {|(k0, _), (k1, _)| k0 <=> k1}.
|
|
456
|
+
map {|(_, v)| v}
|
|
492
457
|
end
|
|
493
458
|
|
|
494
459
|
# Returns a human readable string
|
|
@@ -580,11 +545,8 @@ module Metadata
|
|
|
580
545
|
klass.class_eval do
|
|
581
546
|
define_method(fd.name) do
|
|
582
547
|
if instance_variable_get("@" + fd.name).nil?
|
|
583
|
-
q = __cd__.select(
|
|
584
|
-
instance_var = q.results.first
|
|
585
|
-
if fd.is_a?(CollectionDescriptor) and instance_var.nil?
|
|
586
|
-
instance_var = []
|
|
587
|
-
end
|
|
548
|
+
q = __cd__.select(fd.name + ".*").where(:id => objectId)
|
|
549
|
+
instance_var = q.results.first[fd.name]
|
|
588
550
|
instance_variable_set("@" + fd.name, instance_var)
|
|
589
551
|
end
|
|
590
552
|
return instance_variable_get("@" + fd.name)
|
|
@@ -614,16 +576,14 @@ module Metadata
|
|
|
614
576
|
type = fd.referencedType
|
|
615
577
|
if fd.is_a?(CollectionDescriptor)
|
|
616
578
|
instance_var = []
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
item = type.model.make_new(type.name, item)
|
|
621
|
-
end
|
|
622
|
-
if !item.is_a?(type)
|
|
623
|
-
raise ArgumentError, "Arguments to #{fd.name} in #{@name} must be #{type.name}s"
|
|
624
|
-
end
|
|
625
|
-
instance_var << item
|
|
579
|
+
val.each do |item|
|
|
580
|
+
if item.is_a?(Hash)
|
|
581
|
+
item = type.model.make_new(type.name, item)
|
|
626
582
|
end
|
|
583
|
+
if !item.is_a?(type)
|
|
584
|
+
raise ArgumentError, "Arguments to #{fd.name} in #{@name} must be #{type.name}s"
|
|
585
|
+
end
|
|
586
|
+
instance_var << item
|
|
627
587
|
end
|
|
628
588
|
instance_variable_set("@" + fd.name, instance_var)
|
|
629
589
|
else
|
|
@@ -794,55 +754,11 @@ module Metadata
|
|
|
794
754
|
end
|
|
795
755
|
end
|
|
796
756
|
|
|
797
|
-
# call-seq:
|
|
798
|
-
# end => ClassDescriptor | ReferenceDescriptor | AttributeDescriptor
|
|
799
|
-
#
|
|
800
|
-
# Return the last element of this path
|
|
801
|
-
#
|
|
802
|
-
def end
|
|
803
|
-
return @elements.last
|
|
804
|
-
end
|
|
805
|
-
|
|
806
|
-
# call-seq:
|
|
807
|
-
# prefix => Path
|
|
808
|
-
#
|
|
809
|
-
# Return the Path one above this.
|
|
810
|
-
def prefix
|
|
811
|
-
if @elements.size == 1
|
|
812
|
-
raise PathException, "Root paths do not have a prefix"
|
|
813
|
-
end
|
|
814
|
-
new_str = @elements[0, @elements.size - 1].map {|x| x.name}.join(".")
|
|
815
|
-
return Path.new(new_str, @model, @subclasses)
|
|
816
|
-
end
|
|
817
|
-
|
|
818
|
-
# call-seq:
|
|
819
|
-
# append(part, ...) => Path
|
|
820
|
-
#
|
|
821
|
-
# Return a new path by adding elements to this path.
|
|
822
|
-
#
|
|
823
|
-
def append(*parts)
|
|
824
|
-
new_str = self.to_s + "." + parts.join(".")
|
|
825
|
-
return Path.new(new_str, @model, @subclasses)
|
|
826
|
-
end
|
|
827
|
-
|
|
828
757
|
# Two paths can be said to be equal when they stringify to the same representation.
|
|
829
758
|
def ==(other)
|
|
830
759
|
return self.to_s == other.to_s
|
|
831
760
|
end
|
|
832
761
|
|
|
833
|
-
# Two paths are identical when they have the same everything.
|
|
834
|
-
def eql?(other)
|
|
835
|
-
begin
|
|
836
|
-
return (self == other) && @model.eql?(other.model) && @subclasses.eql?(other.subclasses)
|
|
837
|
-
rescue
|
|
838
|
-
return false
|
|
839
|
-
end
|
|
840
|
-
end
|
|
841
|
-
|
|
842
|
-
def hash
|
|
843
|
-
return 17 * @model.hash * 11 * @subclasses.hash * 3 * to_s.hash
|
|
844
|
-
end
|
|
845
|
-
|
|
846
762
|
# Get the number of elements in the path
|
|
847
763
|
def length
|
|
848
764
|
return @elements.length
|
|
@@ -969,9 +885,6 @@ module Metadata
|
|
|
969
885
|
end
|
|
970
886
|
end
|
|
971
887
|
end
|
|
972
|
-
|
|
973
|
-
class ItemNotFoundError < RuntimeError
|
|
974
|
-
end
|
|
975
888
|
end
|
|
976
889
|
end
|
|
977
890
|
|
data/lib/intermine/query.rb
CHANGED
|
@@ -616,10 +616,7 @@ module InterMine::PathQuery
|
|
|
616
616
|
if y.end_with?("*")
|
|
617
617
|
prefix = y.chomp(".*")
|
|
618
618
|
path = make_path(prefix)
|
|
619
|
-
|
|
620
|
-
prefix + "." + x.name
|
|
621
|
-
}
|
|
622
|
-
add_views(attrs)
|
|
619
|
+
add_views(path.end_cd.attributes.map {|x| prefix + "." + x.name})
|
|
623
620
|
else
|
|
624
621
|
path = make_path(y)
|
|
625
622
|
path = make_path(y.to_s + ".id") unless path.is_attribute?
|
|
@@ -723,11 +720,8 @@ module InterMine::PathQuery
|
|
|
723
720
|
#
|
|
724
721
|
def add_sort_order(path, direction="ASC")
|
|
725
722
|
p = self.path(path)
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
selected.uniq!
|
|
729
|
-
if !selected.include? p.prefix
|
|
730
|
-
raise ArgumentError, "Sort order (#{p}) not on a selected class (#{selected.map {|v| v.to_s}.inspect} in #{self.name || 'unnamed query'})"
|
|
723
|
+
if !@views.include? p
|
|
724
|
+
raise ArgumentError, "Sort order (#{p}) not in view (#{@views.map {|v| v.to_s}.inspect} in #{self.name || 'unnamed query'})"
|
|
731
725
|
end
|
|
732
726
|
@sort_order << SortOrder.new(p, direction)
|
|
733
727
|
return self
|
|
@@ -765,32 +759,6 @@ module InterMine::PathQuery
|
|
|
765
759
|
@constraints << con
|
|
766
760
|
return con
|
|
767
761
|
end
|
|
768
|
-
|
|
769
|
-
def or(*parameters)
|
|
770
|
-
logic = @logic
|
|
771
|
-
new_con = add_constraint(*parameters)
|
|
772
|
-
|
|
773
|
-
if logic
|
|
774
|
-
set_logic(LogicGroup.new(logic, "OR", new_con))
|
|
775
|
-
elsif @constraints.size > 1
|
|
776
|
-
set_logic(@constraints.map {|c| c.code }.join(" or "))
|
|
777
|
-
end
|
|
778
|
-
|
|
779
|
-
return self
|
|
780
|
-
end
|
|
781
|
-
|
|
782
|
-
def and(*parameters)
|
|
783
|
-
logic = @logic
|
|
784
|
-
new_con = add_constraint(*parameters)
|
|
785
|
-
|
|
786
|
-
if logic
|
|
787
|
-
set_logic(LogicGroup.new(logic, "AND", new_con))
|
|
788
|
-
elsif @constraints.size > 1
|
|
789
|
-
set_logic(@constraints.map {|c| c.code }.join(" and "))
|
|
790
|
-
end
|
|
791
|
-
|
|
792
|
-
return self
|
|
793
|
-
end
|
|
794
762
|
|
|
795
763
|
# Returns a Path object constructed from the given path-string,
|
|
796
764
|
# taking the current state of the query into account (its data-model
|
|
@@ -855,7 +823,7 @@ module InterMine::PathQuery
|
|
|
855
823
|
end
|
|
856
824
|
parameters[:values] = subv.to_a
|
|
857
825
|
elsif subv.is_a?(Lists::List)
|
|
858
|
-
if subk == "="
|
|
826
|
+
if subk == "="
|
|
859
827
|
parameters[:op] = "IN"
|
|
860
828
|
elsif subk == "!="
|
|
861
829
|
parameters[:op] = "NOT IN"
|
|
@@ -863,19 +831,6 @@ module InterMine::PathQuery
|
|
|
863
831
|
parameters[:op] = normalised_k
|
|
864
832
|
end
|
|
865
833
|
parameters[:value] = subv.name
|
|
866
|
-
elsif subv.is_a? Query
|
|
867
|
-
if subk == "=" or subk == "<" or subk == "<="
|
|
868
|
-
parameters[:op] = "IN"
|
|
869
|
-
elsif subk == "!="
|
|
870
|
-
parameters[:op] = "NOT IN"
|
|
871
|
-
else
|
|
872
|
-
parameters[:op] = normalised_k
|
|
873
|
-
end
|
|
874
|
-
s = subv.service
|
|
875
|
-
l = s.create_list(subv)
|
|
876
|
-
|
|
877
|
-
parameters[:value] = l.name
|
|
878
|
-
|
|
879
834
|
else
|
|
880
835
|
parameters[:op] = normalised_k
|
|
881
836
|
parameters[:value] = subv
|
|
@@ -988,7 +943,7 @@ module InterMine::PathQuery
|
|
|
988
943
|
@classes = [
|
|
989
944
|
SingleValueConstraint,
|
|
990
945
|
SubClassConstraint,
|
|
991
|
-
LookupConstraint, MultiValueConstraint,
|
|
946
|
+
LookupConstraint, MultiValueConstraint, RangeConstraint,
|
|
992
947
|
UnaryConstraint, LoopConstraint, ListConstraint]
|
|
993
948
|
|
|
994
949
|
@query = query
|
|
@@ -1014,14 +969,9 @@ module InterMine::PathQuery
|
|
|
1014
969
|
|
|
1015
970
|
attr_keys = parameters.keys
|
|
1016
971
|
suitable_classes = @classes.select { |cls|
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
if key.to_s == "op"
|
|
1021
|
-
is_suitable = is_suitable && cls.valid_ops.include?(parameters[key])
|
|
1022
|
-
end
|
|
1023
|
-
}
|
|
1024
|
-
is_suitable
|
|
972
|
+
attr_keys.reduce(true) do |suitable, k|
|
|
973
|
+
suitable && cls.method_defined?(k) && (k.to_s != "op" or cls.valid_ops.include?(parameters[k]))
|
|
974
|
+
end
|
|
1025
975
|
}
|
|
1026
976
|
if suitable_classes.size > 1
|
|
1027
977
|
raise ArgumentError, "More than one class found for #{parameters.inspect}"
|
|
@@ -1402,10 +1352,31 @@ module InterMine::PathQuery
|
|
|
1402
1352
|
end
|
|
1403
1353
|
end
|
|
1404
1354
|
|
|
1355
|
+
class RangeConstraint < MultiValueConstraint
|
|
1356
|
+
|
|
1357
|
+
VALID_OPS = [
|
|
1358
|
+
"WITHIN", "OUTSIDE",
|
|
1359
|
+
"CONTAINS", "DOES NOT CONTAIN",
|
|
1360
|
+
"OVERLAPS", "DOES NOT OVERLAP"
|
|
1361
|
+
]
|
|
1362
|
+
|
|
1363
|
+
def self.valid_ops
|
|
1364
|
+
return VALID_OPS
|
|
1365
|
+
end
|
|
1366
|
+
|
|
1367
|
+
def validate
|
|
1368
|
+
# no-op
|
|
1369
|
+
end
|
|
1370
|
+
end
|
|
1371
|
+
|
|
1405
1372
|
class TemplateMultiValueConstraint < MultiValueConstraint
|
|
1406
1373
|
include TemplateConstraint
|
|
1407
1374
|
end
|
|
1408
1375
|
|
|
1376
|
+
class TemplateRangeConstraint < RangeConstraint
|
|
1377
|
+
include TemplateConstraint
|
|
1378
|
+
end
|
|
1379
|
+
|
|
1409
1380
|
class SortOrder
|
|
1410
1381
|
include PathFeature
|
|
1411
1382
|
attr_accessor :direction
|
data/lib/intermine/results.rb
CHANGED
|
@@ -85,12 +85,12 @@ module InterMine::Results
|
|
|
85
85
|
def [](arg, length=nil)
|
|
86
86
|
unless length.nil?
|
|
87
87
|
raise ArgumentError, "when providing a length, the first argument must be an Integer" unless arg.is_a? Integer
|
|
88
|
-
return @results[arg, length].map {|x|
|
|
88
|
+
return @results[arg, length].map {|x| x["value"]}
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
case arg
|
|
92
92
|
when Range
|
|
93
|
-
return @results[arg].map {|x|
|
|
93
|
+
return @results[arg].map {|x| x["value"]}
|
|
94
94
|
when Integer
|
|
95
95
|
idx = arg
|
|
96
96
|
else
|
|
@@ -101,19 +101,19 @@ module InterMine::Results
|
|
|
101
101
|
|
|
102
102
|
cell = @results[idx]
|
|
103
103
|
|
|
104
|
-
raise IndexError, "Argument out of range" if
|
|
104
|
+
raise IndexError, "Argument out of range" if cell.nil?
|
|
105
105
|
|
|
106
|
-
return
|
|
106
|
+
return cell["value"]
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
# Returns the first value in this row
|
|
110
110
|
def first
|
|
111
|
-
return
|
|
111
|
+
return @results[0]["value"]
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
# Returns the last value in this row
|
|
115
115
|
def last
|
|
116
|
-
return
|
|
116
|
+
return @results.last["value"]
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
# Iterate over the values in this row in the
|
|
@@ -134,11 +134,9 @@ module InterMine::Results
|
|
|
134
134
|
def each(&block)
|
|
135
135
|
if block
|
|
136
136
|
if block.arity == 1
|
|
137
|
-
@results.each {|x| block.call(
|
|
137
|
+
@results.each {|x| block.call(x["value"])}
|
|
138
138
|
else block.arity == 2
|
|
139
|
-
(0 ... @results.size).to_a.each {|i|
|
|
140
|
-
block.call(@columns[i], value_of(@results[i]))
|
|
141
|
-
}
|
|
139
|
+
(0 ... @results.size).to_a.each {|i| block.call(@columns[i], @results[i]["value"])}
|
|
142
140
|
end
|
|
143
141
|
end
|
|
144
142
|
return self
|
|
@@ -156,7 +154,7 @@ module InterMine::Results
|
|
|
156
154
|
|
|
157
155
|
# Return an Array version of the row.
|
|
158
156
|
def to_a
|
|
159
|
-
return @results.map {|x|
|
|
157
|
+
return @results.map {|x| x["value"]}
|
|
160
158
|
end
|
|
161
159
|
|
|
162
160
|
# Return a Hash version of the row. All keys in this
|
|
@@ -187,15 +185,11 @@ module InterMine::Results
|
|
|
187
185
|
# CSV or TSV file. The optional separator argument will be used to delimit
|
|
188
186
|
# columns
|
|
189
187
|
def to_csv(sep="\t")
|
|
190
|
-
return @results.map {|x|
|
|
188
|
+
return @results.map {|x| x["value"].inspect}.join(sep)
|
|
191
189
|
end
|
|
192
190
|
|
|
193
191
|
private
|
|
194
192
|
|
|
195
|
-
def value_of(cell)
|
|
196
|
-
return cell["value"]
|
|
197
|
-
end
|
|
198
|
-
|
|
199
193
|
# Return the index for a string or symbol key.
|
|
200
194
|
def index_for(key)
|
|
201
195
|
if @indexes.nil?
|
|
@@ -215,13 +209,6 @@ module InterMine::Results
|
|
|
215
209
|
end
|
|
216
210
|
end
|
|
217
211
|
|
|
218
|
-
class NewResultRow < ResultsRow
|
|
219
|
-
|
|
220
|
-
def value_of(cell)
|
|
221
|
-
return cell
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
|
|
225
212
|
# The class responsible for retrieving results and processing them
|
|
226
213
|
#
|
|
227
214
|
# query.each_row do |row|
|
|
@@ -263,13 +250,11 @@ module InterMine::Results
|
|
|
263
250
|
|
|
264
251
|
# Iterate over the result set one ResultsRow at a time
|
|
265
252
|
def each_row
|
|
266
|
-
cls = @query.service.version >= 8 ? NewResultRow : ResultsRow
|
|
267
|
-
format = @query.service.version >= 8 ? "json" : "jsonrows"
|
|
268
253
|
processor = lambda {|line|
|
|
269
254
|
x = line.chomp.chomp(",")
|
|
270
|
-
x.empty? ? nil :
|
|
255
|
+
x.empty? ? nil : ResultsRow.new(x, @query.views)
|
|
271
256
|
}
|
|
272
|
-
read_result_set(params(
|
|
257
|
+
read_result_set(params("jsonrows"), processor) {|x|
|
|
273
258
|
yield x
|
|
274
259
|
}
|
|
275
260
|
end
|
data/lib/intermine/service.rb
CHANGED
|
@@ -109,6 +109,7 @@ module InterMine
|
|
|
109
109
|
LIST_INTERSECTION_PATH = "/lists/intersect/json"
|
|
110
110
|
LIST_SUBTRACTION_PATH = "/lists/subtract/json"
|
|
111
111
|
LIST_TAG_PATH = "/list/tags/json"
|
|
112
|
+
LIST_ENRICHMENT_PATH = "/list/enrichment"
|
|
112
113
|
|
|
113
114
|
# The webservice version. An integer that
|
|
114
115
|
# supplies information about what features are supported.
|
data/lib/intermine/version.rb
CHANGED
|
@@ -3,6 +3,9 @@ module Intermine
|
|
|
3
3
|
# Webservice Client Version number
|
|
4
4
|
#
|
|
5
5
|
# Changes:
|
|
6
|
+
# 1.00.00 - Up to make use of new features of the InterMine 1.0 API
|
|
7
|
+
# * Enrichment queries
|
|
8
|
+
# * Range constraints
|
|
6
9
|
# 0.98.11 - * InterMineObjects now lazily fetch their references
|
|
7
10
|
# if nil. Note that while extremely convenient,
|
|
8
11
|
# explicit prefetching will be much more efficient
|
|
@@ -12,10 +15,5 @@ module Intermine
|
|
|
12
15
|
# 0.98.10 - Added status property to lists
|
|
13
16
|
# 0.98.09 - Major changes to results - now with thorough-going Enumerable support
|
|
14
17
|
# 0.98.08 - Added column summary support
|
|
15
|
-
|
|
16
|
-
# - Added support for "json" format (performance) improvement
|
|
17
|
-
# 0.99.01 - Added support for sort-orders on selected classes which are not in the view
|
|
18
|
-
# 0.99.02 - Fixed bug with null values in new result rows (resulting commonly from outer joins)
|
|
19
|
-
# 0.99.03 - Fixed handling of null references and empty collections in lazy reference fetching.
|
|
20
|
-
VERSION = "0.99.03"
|
|
18
|
+
VERSION = "1.00.00"
|
|
21
19
|
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/test_helper.rb"
|
|
2
|
+
|
|
3
|
+
require "test/unit"
|
|
4
|
+
require "intermine/service"
|
|
5
|
+
require "intermine/results"
|
|
6
|
+
|
|
7
|
+
class LiveResultsTest < Test::Unit::TestCase
|
|
8
|
+
|
|
9
|
+
def setup
|
|
10
|
+
@service = Service.new("http://localhost/intermine-test")
|
|
11
|
+
@max = 50
|
|
12
|
+
@q = @service.query("Employee").select("*", "department.*").where(:age => {:lt => @max})
|
|
13
|
+
@empty = @service.query("Employee").where(:name => "some-non-existant-value")
|
|
14
|
+
@exp_count = 82
|
|
15
|
+
@expected_last = "Didier Legu\303\251lec"
|
|
16
|
+
@expected_last_summary = "Vincent"
|
|
17
|
+
@expected_last_obj = "Both Quotes '\""
|
|
18
|
+
@expected_target = 37.02439
|
|
19
|
+
@expected_two_vowels = 31
|
|
20
|
+
@exp_trideps = 5
|
|
21
|
+
@exp_s_deps = 29
|
|
22
|
+
@exp_row_size = 7
|
|
23
|
+
@rows_args = []
|
|
24
|
+
@results_args = []
|
|
25
|
+
@summary_args = []
|
|
26
|
+
@count_args = []
|
|
27
|
+
@dep_size = 3
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def testRowIteration
|
|
31
|
+
count = 0
|
|
32
|
+
@q.rows(*@rows_args).each do |row|
|
|
33
|
+
assert_equal(@exp_row_size, row.size)
|
|
34
|
+
assert(row["age"].is_a? Fixnum)
|
|
35
|
+
assert(row["age"] < @max)
|
|
36
|
+
assert(row["name"].is_a? String)
|
|
37
|
+
count += 1
|
|
38
|
+
end
|
|
39
|
+
assert_equal(@exp_count, count)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def testEmptyRows
|
|
43
|
+
count = 0
|
|
44
|
+
@empty.rows.each do
|
|
45
|
+
count += 1
|
|
46
|
+
end
|
|
47
|
+
assert_equal(0, count)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def testRowMapping
|
|
51
|
+
names = @q.rows(*@rows_args).map {|r| r["name"]}
|
|
52
|
+
assert_equal(@exp_count, names.length)
|
|
53
|
+
assert_equal(@expected_last, names.last)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def testRowFolding
|
|
57
|
+
average = @q.rows(*@rows_args).reduce(0.0) {|m, i| m + i["age"]} / @q.count(*@count_args)
|
|
58
|
+
target = @expected_target
|
|
59
|
+
assert(average > target * 0.999999)
|
|
60
|
+
assert(average < target * 1.000001)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def testRowFiltering
|
|
64
|
+
two_vowels = @q.rows(*@rows_args).select {|r| r["name"].match(/[aeiou]{2}/) }
|
|
65
|
+
assert_equal(@expected_two_vowels, two_vowels.length)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def testObjectIteration
|
|
69
|
+
count = 0
|
|
70
|
+
@q.results(*@results_args).each do |emp|
|
|
71
|
+
assert(emp.is_a? @q.model.table("Employee"))
|
|
72
|
+
assert(emp.age.is_a? Fixnum)
|
|
73
|
+
assert(emp.age < @max)
|
|
74
|
+
assert(emp.name.is_a? String)
|
|
75
|
+
count += 1
|
|
76
|
+
end
|
|
77
|
+
assert_equal(@exp_count, count)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def testEmptyObjects
|
|
81
|
+
count = 0
|
|
82
|
+
@empty.results.each do
|
|
83
|
+
count += 1
|
|
84
|
+
end
|
|
85
|
+
assert_equal(0, count)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def testObjectMapping
|
|
89
|
+
names = @q.results(*@results_args).map {|r| r.name}
|
|
90
|
+
assert_equal(@exp_count, names.length)
|
|
91
|
+
assert_equal(@expected_last_obj, names.last)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def testObjectFolding
|
|
95
|
+
average = @q.results(*@results_args).reduce(0.0) {|m, i| m + i.age} / @q.count(*@count_args)
|
|
96
|
+
target = @expected_target
|
|
97
|
+
assert(average > target * 0.999999, "Checking lower bound on #{average}")
|
|
98
|
+
assert(average < target * 1.000001, "Checking upper bound on #{average}")
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def testObjectFiltering
|
|
102
|
+
emps_in_s_deps = @q.results(*@results_args).select {|o| o.department.name.start_with? "S"}
|
|
103
|
+
assert_equal(@exp_s_deps, emps_in_s_deps.length)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def testSummaryIteration
|
|
107
|
+
count = 0
|
|
108
|
+
@q.summaries("name", *@summary_args).each do |summary|
|
|
109
|
+
assert_equal(1, summary["count"])
|
|
110
|
+
count += 1
|
|
111
|
+
end
|
|
112
|
+
assert_equal(@exp_count, count)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def testEmptySummaries
|
|
116
|
+
count = 0
|
|
117
|
+
@empty.summaries("name").each do
|
|
118
|
+
count += 1
|
|
119
|
+
end
|
|
120
|
+
assert_equal(0, count)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def testSummaryMapping
|
|
124
|
+
names = @q.summaries("name", *@summary_args).map {|s| s["item"]}
|
|
125
|
+
assert_equal(@exp_count, names.length)
|
|
126
|
+
assert_equal(@expected_last_summary, names.last)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def testSummaryFolding
|
|
130
|
+
sum = @q.summaries("name", *@summary_args).reduce(0) {|m, i| m + i["count"]}
|
|
131
|
+
assert_equal(@q.count(*@count_args), sum)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def testSummaryFiltering
|
|
135
|
+
trideps = @q.summaries("department.name", *@summary_args).select {|s| s["count"] == @dep_size}
|
|
136
|
+
assert_equal(@exp_trideps, trideps.length)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
class LiveTemplateResultsTest < LiveResultsTest
|
|
141
|
+
|
|
142
|
+
def setup
|
|
143
|
+
@service = Service.new("http://localhost/intermine-test")
|
|
144
|
+
@q = @service.template("employeesOverACertainAgeFromDepartmentA")
|
|
145
|
+
@empty = @q
|
|
146
|
+
@exp_count = 18
|
|
147
|
+
@expected_last = "Tim Canterbury"
|
|
148
|
+
@expected_last_summary = "Tim Canterbury"
|
|
149
|
+
@expected_last_obj = "Fatou"
|
|
150
|
+
@expected_target = 47.277778
|
|
151
|
+
@expected_two_vowels = 4
|
|
152
|
+
@dep_size = 18
|
|
153
|
+
@exp_trideps = 1
|
|
154
|
+
@exp_s_deps = 18
|
|
155
|
+
@max = 69
|
|
156
|
+
@rows_args = [{"B" => "Sales"}]
|
|
157
|
+
@results_args = [{"B" => "Sales"}]
|
|
158
|
+
@summary_args = [{"B" => "Sales"}]
|
|
159
|
+
@count_args = [{"B" => "Sales"}]
|
|
160
|
+
@exp_row_size = 3
|
|
161
|
+
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/test_helper.rb"
|
|
2
|
+
|
|
3
|
+
require "test/unit"
|
|
4
|
+
require "intermine/service"
|
|
5
|
+
|
|
6
|
+
class LiveSummaryTest < Test::Unit::TestCase
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@service = Service.new("http://localhost/intermine-test")
|
|
10
|
+
@query = @service.query("Employee").where(:age => {:lt => 50})
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def testIteration
|
|
14
|
+
@query.summaries("age").each {|summary|
|
|
15
|
+
assert_equal("37.0243902439024390", summary["average"])
|
|
16
|
+
assert(summary["max"] < 50)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
count = 0
|
|
20
|
+
@query.summaries("name").each {|summary|
|
|
21
|
+
assert_equal(1, summary["count"])
|
|
22
|
+
count += 1
|
|
23
|
+
}
|
|
24
|
+
assert_equal(count, @query.count)
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def testNumericSummary
|
|
29
|
+
summary = @query.summarise("age")
|
|
30
|
+
assert(summary["max"] < 50)
|
|
31
|
+
# Work around float comparison errors, grrr
|
|
32
|
+
assert(summary["average"] > 37.024)
|
|
33
|
+
assert(summary["average"] < 37.025)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def testNonNumericSummary
|
|
37
|
+
summary = @query.summarise("name")
|
|
38
|
+
assert_equal(1, summary["Tim Canterbury"])
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def testTop
|
|
42
|
+
summary = @query.summaries("department.name")
|
|
43
|
+
top = summary.first
|
|
44
|
+
assert_equal("Warehouse", top["item"])
|
|
45
|
+
assert_equal(12, top["count"])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def testTemplateSummary
|
|
49
|
+
template = @service.template("CEO_Rivals")
|
|
50
|
+
template_params = {"A" => {"!=" => "Charles Miner"}}
|
|
51
|
+
|
|
52
|
+
summary = template.summarise("salary", template_params)
|
|
53
|
+
assert_equal(529119.4, summary["average"])
|
|
54
|
+
|
|
55
|
+
summary = template.summarise("company.name", template_params)
|
|
56
|
+
assert_equal(1, summary["Gogirep"])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
data/test/live_test.rb
CHANGED
|
@@ -6,7 +6,7 @@ require "intermine/service"
|
|
|
6
6
|
class LiveDemoTest < Test::Unit::TestCase
|
|
7
7
|
|
|
8
8
|
def setup
|
|
9
|
-
@service = Service.new("localhost/intermine-test", "test-user-token")
|
|
9
|
+
@service = Service.new("http://localhost/intermine-test", "test-user-token")
|
|
10
10
|
@temp_lists = []
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -48,10 +48,10 @@ class LiveDemoTest < Test::Unit::TestCase
|
|
|
48
48
|
def testListEnumerability
|
|
49
49
|
list = @service.list("My-Favourite-Employees")
|
|
50
50
|
names = list.map {|emp| emp.name }
|
|
51
|
-
exp = ["David Brent", "Neil Godwin", "Bernd Stromberg", "Timo Becker"]
|
|
51
|
+
exp = [ "David Brent", "Neil Godwin", "Bernd Stromberg", "Timo Becker"]
|
|
52
52
|
assert_equal(exp, names)
|
|
53
53
|
|
|
54
|
-
old = list.select {|emp| emp.age >
|
|
54
|
+
old = list.select {|emp| emp.age > 43}
|
|
55
55
|
assert_equal(1, old.size)
|
|
56
56
|
assert_equal("Neil Godwin", old.first.name)
|
|
57
57
|
|
|
@@ -63,23 +63,23 @@ class LiveDemoTest < Test::Unit::TestCase
|
|
|
63
63
|
list = @service.list("My-Favourite-Employees")
|
|
64
64
|
|
|
65
65
|
deps = list.map {|emp| emp.department.name }
|
|
66
|
-
exp = ["Sales", "Human Resources",
|
|
67
|
-
"Schadensregulierung M-Z", "Schadensregulierung"]
|
|
66
|
+
exp = ["Sales", "Human Resources", "Schadensregulierung M-Z", "Schadensregulierung"]
|
|
68
67
|
assert_equal(exp, deps)
|
|
69
68
|
|
|
70
69
|
comps = list.map {|emp| emp.department.company.name }
|
|
71
|
-
exp = [
|
|
72
|
-
"Capitol Versicherung AG", "Capitol Versicherung AG"]
|
|
70
|
+
exp = ["Wernham-Hogg", "Wernham-Hogg", "Capitol Versicherung AG", "Capitol Versicherung AG"]
|
|
73
71
|
assert_equal(exp, comps)
|
|
74
72
|
end
|
|
75
73
|
|
|
76
74
|
def testLazyCollectionFetching
|
|
77
75
|
list = @service.list("My-Favourite-Employees")
|
|
78
76
|
emps = list.map {|manager| manager.department.employees.map {|employee| employee.age} }
|
|
79
|
-
exp = [
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
exp = [
|
|
78
|
+
[34, 36, 41, 55, 61, 61],
|
|
79
|
+
[44, 49, 62],
|
|
80
|
+
[30, 37, 45, 46, 58, 64],
|
|
81
|
+
[36, 37, 39, 49, 57, 59]
|
|
82
|
+
]
|
|
83
83
|
assert_equal(exp, emps)
|
|
84
84
|
|
|
85
85
|
sum = list.reduce(0) {|m, manager| m + manager.department.employees.reduce(0) {|n, emp| n + emp.age}}
|
|
@@ -130,15 +130,10 @@ class LiveDemoTest < Test::Unit::TestCase
|
|
|
130
130
|
assert_equal(tags.sort, new_list.tags.sort)
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
-
def
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
assert_equal(2, @service.query("Bank").where("Bank" => {:not_in => q2}).count)
|
|
138
|
-
|
|
139
|
-
l = @service.subtract([q1], [q2])
|
|
140
|
-
@temp_lists << l
|
|
141
|
-
assert_equal(2, l.size)
|
|
133
|
+
def testEnrichment
|
|
134
|
+
l = @service.list("My-Favourite-Employees")
|
|
135
|
+
contractors = l.calculate_enrichment :contractor_enrichment, :maxp => 1.0
|
|
136
|
+
assert_equal("Vikram", contractors.first[:identifier])
|
|
142
137
|
end
|
|
143
138
|
|
|
144
139
|
end
|
data/test/test_query.rb
CHANGED
|
@@ -640,6 +640,20 @@ class TestQuery < Test::Unit::TestCase
|
|
|
640
640
|
assert_equal(conA.values, %w{Sales Marketing Janitorial})
|
|
641
641
|
end
|
|
642
642
|
|
|
643
|
+
def test_range_constraints
|
|
644
|
+
query = InterMine::PathQuery::Query.new(@model, "Employee")
|
|
645
|
+
query.add_constraint({
|
|
646
|
+
:path => "age",
|
|
647
|
+
:op => "WITHIN",
|
|
648
|
+
:values => %w{1..10 30..35}
|
|
649
|
+
})
|
|
650
|
+
|
|
651
|
+
conA = query.constraints.first
|
|
652
|
+
assert_equal(conA.path.to_s, "Employee.age")
|
|
653
|
+
assert_equal(conA.op, "WITHIN")
|
|
654
|
+
assert_equal(conA.values, ["1..10", "30..35"])
|
|
655
|
+
end
|
|
656
|
+
|
|
643
657
|
def test_bad_multi_constraint
|
|
644
658
|
query = InterMine::PathQuery::Query.new(@model, "Employee")
|
|
645
659
|
assert_raise ArgumentError do
|
|
@@ -848,12 +862,6 @@ class TestQuery < Test::Unit::TestCase
|
|
|
848
862
|
|
|
849
863
|
assert_equal(query.sort_order.last.path, "Employee.name")
|
|
850
864
|
assert_equal(query.sort_order.last.direction, "DESC")
|
|
851
|
-
|
|
852
|
-
query.add_sort_order("fullTime")
|
|
853
|
-
|
|
854
|
-
assert_equal(query.sort_order.last.path, "Employee.fullTime")
|
|
855
|
-
assert_equal(query.sort_order.last.direction, "ASC")
|
|
856
|
-
|
|
857
865
|
end
|
|
858
866
|
|
|
859
867
|
def test_subclassed_sort_order
|
|
@@ -981,6 +989,11 @@ class TestQuery < Test::Unit::TestCase
|
|
|
981
989
|
:value => "zop",
|
|
982
990
|
:extra_value => "zip"
|
|
983
991
|
})
|
|
992
|
+
query.add_constraint({
|
|
993
|
+
:path => "age",
|
|
994
|
+
:op => "WITHIN",
|
|
995
|
+
:values => %w{1..10 30..35}
|
|
996
|
+
})
|
|
984
997
|
query.add_constraint({
|
|
985
998
|
:path => "Employee",
|
|
986
999
|
:sub_class => "Manager"
|
|
@@ -998,6 +1011,9 @@ class TestQuery < Test::Unit::TestCase
|
|
|
998
1011
|
"<constraint loopPath='Employee.department.manager' op='=' code='E' path='Employee'/>" +
|
|
999
1012
|
"<constraint op='LOOKUP' code='F' value='quux' path='Employee'/>" +
|
|
1000
1013
|
"<constraint extraValue='zip' op='LOOKUP' code='G' value='zop' path='Employee'/>" +
|
|
1014
|
+
"<constraint op='WITHIN' code='H' path='Employee.age'>" +
|
|
1015
|
+
"<value>1..10</value><value>30..35</value>" +
|
|
1016
|
+
"</constraint>" +
|
|
1001
1017
|
"</query>"
|
|
1002
1018
|
|
|
1003
1019
|
compare_xml(expected, query.to_xml.to_s)
|
data/test/test_result_row.rb
CHANGED
|
@@ -12,14 +12,9 @@ class TestResults < Test::Unit::TestCase
|
|
|
12
12
|
super
|
|
13
13
|
file = File.new(
|
|
14
14
|
File.dirname(__FILE__) + "/data/resultrow.json", "r")
|
|
15
|
-
file2 = File.new(
|
|
16
|
-
File.dirname(__FILE__) + "/data/resultrow_new.json", "r")
|
|
17
15
|
@data = file.read
|
|
18
|
-
@data2 = file2.read
|
|
19
16
|
@json = JSON.parse(@data)
|
|
20
|
-
@json2 = JSON.parse(@data2)
|
|
21
17
|
@view = ["Company.departments.name","Company.departments.manager.name", "Company.departments.manager.age"]
|
|
22
|
-
@view2 = ["Company.departments.name","Company.departments.manager.name", "Company.departments.manager.age", "Company.address.address"]
|
|
23
18
|
@bad_view = ["Company.departments.name","Company.departments.manager.name"]
|
|
24
19
|
end
|
|
25
20
|
|
|
@@ -47,31 +42,6 @@ class TestResults < Test::Unit::TestCase
|
|
|
47
42
|
end
|
|
48
43
|
end
|
|
49
44
|
|
|
50
|
-
def test_array_access2
|
|
51
|
-
|
|
52
|
-
rr = NewResultRow.new(@data2, @view2)
|
|
53
|
-
|
|
54
|
-
assert_equal(rr[0], "DepartmentA1")
|
|
55
|
-
assert_equal(rr[1], "EmployeeA1")
|
|
56
|
-
|
|
57
|
-
rr = NewResultRow.new(@json2, @view2)
|
|
58
|
-
|
|
59
|
-
assert_equal(rr[0], "DepartmentA1")
|
|
60
|
-
assert_equal(rr[1], "EmployeeA1")
|
|
61
|
-
|
|
62
|
-
assert_equal(rr[1..2], ["EmployeeA1", 33])
|
|
63
|
-
assert_equal(rr[0, 2], ["DepartmentA1", "EmployeeA1"])
|
|
64
|
-
|
|
65
|
-
assert_equal(rr.first, "DepartmentA1")
|
|
66
|
-
assert_equal(rr[3], nil)
|
|
67
|
-
assert_equal(rr.last, nil)
|
|
68
|
-
|
|
69
|
-
assert_raise IndexError do
|
|
70
|
-
rr[4]
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
end
|
|
74
|
-
|
|
75
45
|
def test_array_access
|
|
76
46
|
|
|
77
47
|
rr = ResultsRow.new(@data, @view)
|
data/test/test_sugar.rb
CHANGED
|
@@ -32,13 +32,14 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
|
32
32
|
|
|
33
33
|
def test_view_expansion
|
|
34
34
|
q = @model.table("Employee").select("*", "department.*")
|
|
35
|
-
expected = [
|
|
35
|
+
expected = [
|
|
36
|
+
"Employee.age",
|
|
36
37
|
"Employee.end",
|
|
37
|
-
"Employee.id",
|
|
38
38
|
"Employee.fullTime",
|
|
39
|
-
"Employee.
|
|
40
|
-
"Employee.
|
|
41
|
-
"Employee.department.id"
|
|
39
|
+
"Employee.id",
|
|
40
|
+
"Employee.name",
|
|
41
|
+
"Employee.department.id",
|
|
42
|
+
"Employee.department.name"]
|
|
42
43
|
|
|
43
44
|
assert_equal(expected, q.views.map {|x| x.to_s})
|
|
44
45
|
end
|
|
@@ -50,7 +51,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
|
50
51
|
where(:name => {"=" => nil}).
|
|
51
52
|
where(:fullTime => {"!=" => nil})
|
|
52
53
|
|
|
53
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
|
54
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
|
54
55
|
"<constraint op='IS NULL' code='A' path='Employee.age'/>" +
|
|
55
56
|
"<constraint op='IS NULL' code='B' path='Employee.name'/>" +
|
|
56
57
|
"<constraint op='IS NOT NULL' code='C' path='Employee.fullTime'/>" +
|
|
@@ -68,7 +69,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
|
68
69
|
where("department.name" => {:contains => "foo"}).
|
|
69
70
|
where(:name => {"!=" => "bar"})
|
|
70
71
|
|
|
71
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
|
72
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
|
72
73
|
"<constraint op='=' code='A' value='foo' path='Employee.name'/>" +
|
|
73
74
|
"<constraint op='=' code='B' value='10' path='Employee.age'/>" +
|
|
74
75
|
"<constraint op='<' code='C' value='200' path='Employee.end'/>" +
|
|
@@ -90,7 +91,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
|
90
91
|
where(:name => {:ne => "bar"}).
|
|
91
92
|
where(:name => {:== => "zop"})
|
|
92
93
|
|
|
93
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
|
94
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
|
94
95
|
"<constraint op='<' code='A' value='100' path='Employee.age'/>" +
|
|
95
96
|
"<constraint op='>' code='B' value='200' path='Employee.age'/>" +
|
|
96
97
|
"<constraint op='<=' code='C' value='300' path='Employee.age'/>" +
|
|
@@ -110,7 +111,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
|
110
111
|
where(:department => {:lookup => "foo"}).
|
|
111
112
|
where("department.company" => {:lookup => "foo", :with => "extra"})
|
|
112
113
|
|
|
113
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
|
114
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
|
114
115
|
"<constraint op='LOOKUP' code='A' value='foo' path='Employee.department'/>" +
|
|
115
116
|
"<constraint extraValue='extra' op='LOOKUP' code='B' value='foo' path='Employee.department.company'/>" +
|
|
116
117
|
"</query>"
|
|
@@ -127,7 +128,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
|
127
128
|
where("Employee.department" => {:in => "a list"}).
|
|
128
129
|
where("Employee.department.company" => {:not_in => "a list"})
|
|
129
130
|
|
|
130
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
|
131
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
|
131
132
|
"<constraint op='IN' code='A' value='test-list' path='Employee'/>" +
|
|
132
133
|
"<constraint op='IN' code='B' value='test-list' path='Employee.department.manager'/>" +
|
|
133
134
|
"<constraint op='NOT IN' code='C' value='test-list' path='Employee.department.manager'/>" +
|
|
@@ -152,7 +153,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
|
152
153
|
where("department.manager.age" => {:none_of => [46, 47]}).
|
|
153
154
|
where("department.manager.end" => {:one_of => [56, 57]})
|
|
154
155
|
|
|
155
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
|
156
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
|
156
157
|
"<constraint op='ONE OF' code='A' path='Employee.age'>" +
|
|
157
158
|
"<value>30</value><value>31</value><value>32</value><value>33</value><value>34</value><value>35</value>" +
|
|
158
159
|
"</constraint>" +
|
|
@@ -194,7 +195,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
|
194
195
|
where("department.company.CEO" => {:is => "department.manager"}).
|
|
195
196
|
where("department.company.CEO" => {:is_not => "department.employees"})
|
|
196
197
|
|
|
197
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
|
198
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
|
198
199
|
"<constraint op='=' loopPath='Employee.department.manager' code='A' path='Employee.department.company.CEO'/>" +
|
|
199
200
|
"<constraint op='!=' loopPath='Employee.department.employees' code='B' path='Employee.department.company.CEO'/>" +
|
|
200
201
|
"</query>"
|
|
@@ -209,7 +210,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
|
209
210
|
where("department.employees" => manager).
|
|
210
211
|
where("department.employees" => {:sub_class => "CEO"})
|
|
211
212
|
|
|
212
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
|
213
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
|
213
214
|
"<constraint type='Manager' path='Employee.department.employees'/>" +
|
|
214
215
|
"<constraint type='CEO' path='Employee.department.employees'/>" +
|
|
215
216
|
"</query>"
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: intermine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 23
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
|
+
- 1
|
|
7
8
|
- 0
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
version: 0.99.03
|
|
9
|
+
- 0
|
|
10
|
+
version: 1.00.00
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Alex Kalderimis
|
|
@@ -15,7 +15,7 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date: 2012-
|
|
18
|
+
date: 2012-10-08 00:00:00 Z
|
|
19
19
|
dependencies:
|
|
20
20
|
- !ruby/object:Gem::Dependency
|
|
21
21
|
name: json
|
|
@@ -133,6 +133,8 @@ files:
|
|
|
133
133
|
- test/data/resultrow.json
|
|
134
134
|
- test/data/resultset.json
|
|
135
135
|
- test/data/testmodel_model.xml
|
|
136
|
+
- test/live_results.rb
|
|
137
|
+
- test/live_summary_test.rb
|
|
136
138
|
- test/live_test.rb
|
|
137
139
|
- test/test.rb
|
|
138
140
|
- test/test_helper.rb
|
|
@@ -148,7 +150,6 @@ files:
|
|
|
148
150
|
- LICENCE
|
|
149
151
|
- Rakefile
|
|
150
152
|
- README.rdoc
|
|
151
|
-
- TODO
|
|
152
153
|
- Gemfile
|
|
153
154
|
- contact_header.rdoc
|
|
154
155
|
homepage: http://www.intermine.org
|
|
@@ -184,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
184
185
|
requirements: []
|
|
185
186
|
|
|
186
187
|
rubyforge_project: intermine
|
|
187
|
-
rubygems_version: 1.
|
|
188
|
+
rubygems_version: 1.8.15
|
|
188
189
|
signing_key:
|
|
189
190
|
specification_version: 3
|
|
190
191
|
summary: Webservice Client Library for InterMine Data-Warehouses
|