intermine 0.98.11 → 0.99.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/TODO +3 -0
- data/lib/intermine/lists.rb +20 -8
- data/lib/intermine/model.rb +87 -0
- data/lib/intermine/query.rb +40 -1
- data/lib/intermine/results.rb +26 -11
- data/lib/intermine/version.rb +3 -1
- data/test/live_test.rb +25 -14
- metadata +8 -9
data/lib/intermine/lists.rb
CHANGED
|
@@ -675,13 +675,10 @@ module InterMine::Lists
|
|
|
675
675
|
def make_list_names(objs)
|
|
676
676
|
current_names = list_names
|
|
677
677
|
return objs.map do |x|
|
|
678
|
-
case
|
|
679
|
-
when List
|
|
680
|
-
|
|
681
|
-
when
|
|
682
|
-
create_list(x).name
|
|
683
|
-
when current_names.include?(x.to_s)
|
|
684
|
-
x.to_s
|
|
678
|
+
case
|
|
679
|
+
when x.is_a?(List) then x.name
|
|
680
|
+
when x.respond_to?(:list_upload_uri) then create_list(x).name
|
|
681
|
+
when current_names.include?(x.to_s) then x.to_s
|
|
685
682
|
else
|
|
686
683
|
raise ArgumentError, "#{x} is not a list you can access"
|
|
687
684
|
end
|
|
@@ -711,15 +708,17 @@ module InterMine::Lists
|
|
|
711
708
|
else
|
|
712
709
|
begin
|
|
713
710
|
container = JSON.parse(response.body)
|
|
714
|
-
|
|
711
|
+
err = container["error"]
|
|
715
712
|
rescue
|
|
716
713
|
response.error!
|
|
717
714
|
end
|
|
715
|
+
raise ServiceError, container["error"]
|
|
718
716
|
end
|
|
719
717
|
end
|
|
720
718
|
|
|
721
719
|
# Routine for creating a list from a PathQuery::Query
|
|
722
720
|
def create_list_from_query(query, tags=[], name=nil, description=nil)
|
|
721
|
+
query = get_listable_query(query)
|
|
723
722
|
uri = query.list_upload_uri
|
|
724
723
|
list_params = {
|
|
725
724
|
"listName" => name,
|
|
@@ -731,6 +730,19 @@ module InterMine::Lists
|
|
|
731
730
|
return Net::HTTP.post_form(URI.parse(uri), params)
|
|
732
731
|
end
|
|
733
732
|
|
|
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
|
+
|
|
734
746
|
# Routine for creating a List in a webservice from a list of Ids.
|
|
735
747
|
def create_list_from_ids(ids, type, tags=[], name=nil, description=nil)
|
|
736
748
|
if @service.model.get_cd(type).nil?
|
data/lib/intermine/model.rb
CHANGED
|
@@ -402,6 +402,46 @@ 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
|
+
|
|
405
445
|
# call-seq:
|
|
406
446
|
# where(*constraints) => PathQuery::Query
|
|
407
447
|
#
|
|
@@ -749,11 +789,55 @@ module Metadata
|
|
|
749
789
|
end
|
|
750
790
|
end
|
|
751
791
|
|
|
792
|
+
# call-seq:
|
|
793
|
+
# end => ClassDescriptor | ReferenceDescriptor | AttributeDescriptor
|
|
794
|
+
#
|
|
795
|
+
# Return the last element of this path
|
|
796
|
+
#
|
|
797
|
+
def end
|
|
798
|
+
return @elements.last
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
# call-seq:
|
|
802
|
+
# prefix => Path
|
|
803
|
+
#
|
|
804
|
+
# Return the Path one above this.
|
|
805
|
+
def prefix
|
|
806
|
+
if @elements.size == 1
|
|
807
|
+
raise PathException, "Root paths do not have a prefix"
|
|
808
|
+
end
|
|
809
|
+
new_str = @elements[0, @elements.size - 1].map {|x| x.name}.join(".")
|
|
810
|
+
return Path.new(new_str, @model, @subclasses)
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
# call-seq:
|
|
814
|
+
# append(part, ...) => Path
|
|
815
|
+
#
|
|
816
|
+
# Return a new path by adding elements to this path.
|
|
817
|
+
#
|
|
818
|
+
def append(*parts)
|
|
819
|
+
new_str = self.to_s + "." + parts.join(".")
|
|
820
|
+
return Path.new(new_str, @model, @subclasses)
|
|
821
|
+
end
|
|
822
|
+
|
|
752
823
|
# Two paths can be said to be equal when they stringify to the same representation.
|
|
753
824
|
def ==(other)
|
|
754
825
|
return self.to_s == other.to_s
|
|
755
826
|
end
|
|
756
827
|
|
|
828
|
+
# Two paths are identical when they have the same everything.
|
|
829
|
+
def eql?(other)
|
|
830
|
+
begin
|
|
831
|
+
return (self == other) && @model.eql?(other.model) && @subclasses.eql?(other.subclasses)
|
|
832
|
+
rescue
|
|
833
|
+
return false
|
|
834
|
+
end
|
|
835
|
+
end
|
|
836
|
+
|
|
837
|
+
def hash
|
|
838
|
+
return 17 * @model.hash * 11 * @subclasses.hash * 3 * to_s.hash
|
|
839
|
+
end
|
|
840
|
+
|
|
757
841
|
# Get the number of elements in the path
|
|
758
842
|
def length
|
|
759
843
|
return @elements.length
|
|
@@ -880,6 +964,9 @@ module Metadata
|
|
|
880
964
|
end
|
|
881
965
|
end
|
|
882
966
|
end
|
|
967
|
+
|
|
968
|
+
class ItemNotFoundError < RuntimeError
|
|
969
|
+
end
|
|
883
970
|
end
|
|
884
971
|
end
|
|
885
972
|
|
data/lib/intermine/query.rb
CHANGED
|
@@ -762,6 +762,32 @@ module InterMine::PathQuery
|
|
|
762
762
|
@constraints << con
|
|
763
763
|
return con
|
|
764
764
|
end
|
|
765
|
+
|
|
766
|
+
def or(*parameters)
|
|
767
|
+
logic = @logic
|
|
768
|
+
new_con = add_constraint(*parameters)
|
|
769
|
+
|
|
770
|
+
if logic
|
|
771
|
+
set_logic(LogicGroup.new(logic, "OR", new_con))
|
|
772
|
+
elsif @constraints.size > 1
|
|
773
|
+
set_logic(@constraints.map {|c| c.code }.join(" or "))
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
return self
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
def and(*parameters)
|
|
780
|
+
logic = @logic
|
|
781
|
+
new_con = add_constraint(*parameters)
|
|
782
|
+
|
|
783
|
+
if logic
|
|
784
|
+
set_logic(LogicGroup.new(logic, "AND", new_con))
|
|
785
|
+
elsif @constraints.size > 1
|
|
786
|
+
set_logic(@constraints.map {|c| c.code }.join(" and "))
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
return self
|
|
790
|
+
end
|
|
765
791
|
|
|
766
792
|
# Returns a Path object constructed from the given path-string,
|
|
767
793
|
# taking the current state of the query into account (its data-model
|
|
@@ -826,7 +852,7 @@ module InterMine::PathQuery
|
|
|
826
852
|
end
|
|
827
853
|
parameters[:values] = subv.to_a
|
|
828
854
|
elsif subv.is_a?(Lists::List)
|
|
829
|
-
if subk == "="
|
|
855
|
+
if subk == "=" or subk == "<" or subk == "<="
|
|
830
856
|
parameters[:op] = "IN"
|
|
831
857
|
elsif subk == "!="
|
|
832
858
|
parameters[:op] = "NOT IN"
|
|
@@ -834,6 +860,19 @@ module InterMine::PathQuery
|
|
|
834
860
|
parameters[:op] = normalised_k
|
|
835
861
|
end
|
|
836
862
|
parameters[:value] = subv.name
|
|
863
|
+
elsif subv.is_a? Query
|
|
864
|
+
if subk == "=" or subk == "<" or subk == "<="
|
|
865
|
+
parameters[:op] = "IN"
|
|
866
|
+
elsif subk == "!="
|
|
867
|
+
parameters[:op] = "NOT IN"
|
|
868
|
+
else
|
|
869
|
+
parameters[:op] = normalised_k
|
|
870
|
+
end
|
|
871
|
+
s = subv.service
|
|
872
|
+
l = s.create_list(subv)
|
|
873
|
+
|
|
874
|
+
parameters[:value] = l.name
|
|
875
|
+
|
|
837
876
|
else
|
|
838
877
|
parameters[:op] = normalised_k
|
|
839
878
|
parameters[:value] = subv
|
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| x
|
|
88
|
+
return @results[arg, length].map {|x| value_of(x)}
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
case arg
|
|
92
92
|
when Range
|
|
93
|
-
return @results[arg].map {|x| x
|
|
93
|
+
return @results[arg].map {|x| value_of(x)}
|
|
94
94
|
when Integer
|
|
95
95
|
idx = arg
|
|
96
96
|
else
|
|
@@ -103,17 +103,17 @@ module InterMine::Results
|
|
|
103
103
|
|
|
104
104
|
raise IndexError, "Argument out of range" if cell.nil?
|
|
105
105
|
|
|
106
|
-
return cell
|
|
106
|
+
return value_of(cell)
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
# Returns the first value in this row
|
|
110
110
|
def first
|
|
111
|
-
return @results[0]
|
|
111
|
+
return value_of(@results[0])
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
# Returns the last value in this row
|
|
115
115
|
def last
|
|
116
|
-
return @results.last
|
|
116
|
+
return value_of(@results.last)
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
# Iterate over the values in this row in the
|
|
@@ -134,9 +134,11 @@ module InterMine::Results
|
|
|
134
134
|
def each(&block)
|
|
135
135
|
if block
|
|
136
136
|
if block.arity == 1
|
|
137
|
-
@results.each {|x| block.call(x
|
|
137
|
+
@results.each {|x| block.call(value_of(x))}
|
|
138
138
|
else block.arity == 2
|
|
139
|
-
(0 ... @results.size).to_a.each {|i|
|
|
139
|
+
(0 ... @results.size).to_a.each {|i|
|
|
140
|
+
block.call(@columns[i], value_of(@results[i]))
|
|
141
|
+
}
|
|
140
142
|
end
|
|
141
143
|
end
|
|
142
144
|
return self
|
|
@@ -154,7 +156,7 @@ module InterMine::Results
|
|
|
154
156
|
|
|
155
157
|
# Return an Array version of the row.
|
|
156
158
|
def to_a
|
|
157
|
-
return @results.map {|x| x
|
|
159
|
+
return @results.map {|x| value_of(x)}
|
|
158
160
|
end
|
|
159
161
|
|
|
160
162
|
# Return a Hash version of the row. All keys in this
|
|
@@ -185,11 +187,15 @@ module InterMine::Results
|
|
|
185
187
|
# CSV or TSV file. The optional separator argument will be used to delimit
|
|
186
188
|
# columns
|
|
187
189
|
def to_csv(sep="\t")
|
|
188
|
-
return @results.map {|x| x
|
|
190
|
+
return @results.map {|x| value_of(x).inspect}.join(sep)
|
|
189
191
|
end
|
|
190
192
|
|
|
191
193
|
private
|
|
192
194
|
|
|
195
|
+
def value_of(cell)
|
|
196
|
+
return cell["value"]
|
|
197
|
+
end
|
|
198
|
+
|
|
193
199
|
# Return the index for a string or symbol key.
|
|
194
200
|
def index_for(key)
|
|
195
201
|
if @indexes.nil?
|
|
@@ -209,6 +215,13 @@ module InterMine::Results
|
|
|
209
215
|
end
|
|
210
216
|
end
|
|
211
217
|
|
|
218
|
+
class NewResultRow < ResultsRow
|
|
219
|
+
|
|
220
|
+
def value_of(cell)
|
|
221
|
+
return cell
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
212
225
|
# The class responsible for retrieving results and processing them
|
|
213
226
|
#
|
|
214
227
|
# query.each_row do |row|
|
|
@@ -250,11 +263,13 @@ module InterMine::Results
|
|
|
250
263
|
|
|
251
264
|
# Iterate over the result set one ResultsRow at a time
|
|
252
265
|
def each_row
|
|
266
|
+
cls = @query.service.version >= 8 ? NewResultRow : ResultsRow
|
|
267
|
+
format = @query.service.version >= 8 ? "json" : "jsonrows"
|
|
253
268
|
processor = lambda {|line|
|
|
254
269
|
x = line.chomp.chomp(",")
|
|
255
|
-
x.empty? ? nil :
|
|
270
|
+
x.empty? ? nil : cls.new(x, @query.views)
|
|
256
271
|
}
|
|
257
|
-
read_result_set(params(
|
|
272
|
+
read_result_set(params(format), processor) {|x|
|
|
258
273
|
yield x
|
|
259
274
|
}
|
|
260
275
|
end
|
data/lib/intermine/version.rb
CHANGED
|
@@ -12,5 +12,7 @@ module Intermine
|
|
|
12
12
|
# 0.98.10 - Added status property to lists
|
|
13
13
|
# 0.98.09 - Major changes to results - now with thorough-going Enumerable support
|
|
14
14
|
# 0.98.08 - Added column summary support
|
|
15
|
-
|
|
15
|
+
# 0.99.00 - Added coercion from query to lists in "IN/NOT IN" constraints
|
|
16
|
+
# - Added support for "json" format (performance) improvement
|
|
17
|
+
VERSION = "0.99.00"
|
|
16
18
|
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("
|
|
9
|
+
@service = Service.new("localhost/intermine-test", "test-user-token")
|
|
10
10
|
@temp_lists = []
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -48,42 +48,42 @@ 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 = ["
|
|
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 > 42}
|
|
55
55
|
assert_equal(1, old.size)
|
|
56
|
-
assert_equal("
|
|
56
|
+
assert_equal("Neil Godwin", old.first.name)
|
|
57
57
|
|
|
58
58
|
sum = list.reduce(0) {|m, i| m + i.age}
|
|
59
|
-
assert_equal(
|
|
59
|
+
assert_equal(159, sum)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def testLazyReferenceFetching
|
|
63
63
|
list = @service.list("My-Favourite-Employees")
|
|
64
64
|
|
|
65
65
|
deps = list.map {|emp| emp.department.name }
|
|
66
|
-
exp = ["
|
|
67
|
-
"
|
|
66
|
+
exp = ["Sales", "Human Resources",
|
|
67
|
+
"Schadensregulierung M-Z", "Schadensregulierung"]
|
|
68
68
|
assert_equal(exp, deps)
|
|
69
69
|
|
|
70
70
|
comps = list.map {|emp| emp.department.company.name }
|
|
71
|
-
exp = [
|
|
72
|
-
"
|
|
71
|
+
exp = [ "Wernham-Hogg","Wernham-Hogg",
|
|
72
|
+
"Capitol Versicherung AG", "Capitol Versicherung AG"]
|
|
73
73
|
assert_equal(exp, comps)
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def testLazyCollectionFetching
|
|
77
77
|
list = @service.list("My-Favourite-Employees")
|
|
78
78
|
emps = list.map {|manager| manager.department.employees.map {|employee| employee.age} }
|
|
79
|
-
exp = [[
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
exp = [[34, 36, 41, 55, 61, 61],
|
|
80
|
+
[44, 49, 62],
|
|
81
|
+
[30, 37, 45, 46, 58, 64],
|
|
82
|
+
[36, 37, 39, 49, 57, 59]]
|
|
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}}
|
|
86
|
-
assert_equal(
|
|
86
|
+
assert_equal(1000, sum)
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
def testListCreation
|
|
@@ -130,4 +130,15 @@ class LiveDemoTest < Test::Unit::TestCase
|
|
|
130
130
|
assert_equal(tags.sort, new_list.tags.sort)
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
+
def testCoercingQueriesToLists
|
|
134
|
+
q1 = @service.query("Bank")
|
|
135
|
+
q2 = @service.query("Bank").where("corporateCustomers.id" => {'!=' => nil})
|
|
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)
|
|
142
|
+
end
|
|
143
|
+
|
|
133
144
|
end
|
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:
|
|
5
|
-
prerelease:
|
|
4
|
+
hash: 403
|
|
5
|
+
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
version: 0.
|
|
8
|
+
- 99
|
|
9
|
+
- 0
|
|
10
|
+
version: 0.99.00
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Alex Kalderimis
|
|
@@ -15,8 +15,7 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date: 2011-
|
|
19
|
-
default_executable:
|
|
18
|
+
date: 2011-12-12 00:00:00 Z
|
|
20
19
|
dependencies:
|
|
21
20
|
- !ruby/object:Gem::Dependency
|
|
22
21
|
name: json
|
|
@@ -149,9 +148,9 @@ files:
|
|
|
149
148
|
- LICENCE
|
|
150
149
|
- Rakefile
|
|
151
150
|
- README.rdoc
|
|
151
|
+
- TODO
|
|
152
152
|
- Gemfile
|
|
153
153
|
- contact_header.rdoc
|
|
154
|
-
has_rdoc: true
|
|
155
154
|
homepage: http://www.intermine.org
|
|
156
155
|
licenses:
|
|
157
156
|
- LGPL
|
|
@@ -185,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
185
184
|
requirements: []
|
|
186
185
|
|
|
187
186
|
rubyforge_project: intermine
|
|
188
|
-
rubygems_version: 1.
|
|
187
|
+
rubygems_version: 1.7.2
|
|
189
188
|
signing_key:
|
|
190
189
|
specification_version: 3
|
|
191
190
|
summary: Webservice Client Library for InterMine Data-Warehouses
|