coopy 0.6.4.1 → 1.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +7 -0
- data/LICENSE.md +22 -0
- data/README.md +59 -0
- data/Rakefile +4 -6
- data/coopy.gemspec +26 -0
- data/lib/coopy.rb +32 -175
- data/lib/coopy/alignment.rb +260 -0
- data/lib/coopy/bag.rb +17 -0
- data/lib/coopy/cell_info.rb +24 -0
- data/lib/coopy/change_type.rb +10 -0
- data/lib/coopy/compare_flags.rb +62 -0
- data/lib/coopy/compare_table.rb +327 -0
- data/lib/coopy/coopy.rb +22 -0
- data/lib/coopy/cross_match.rb +10 -0
- data/lib/coopy/csv_table.rb +51 -0
- data/lib/coopy/diff_render.rb +307 -0
- data/lib/coopy/index.rb +73 -0
- data/lib/coopy/index_item.rb +17 -0
- data/lib/coopy/index_pair.rb +72 -0
- data/lib/coopy/mover.rb +123 -0
- data/lib/coopy/ordering.rb +27 -0
- data/lib/coopy/row.rb +9 -0
- data/lib/coopy/simple_cell.rb +15 -0
- data/lib/coopy/simple_table.rb +144 -0
- data/lib/coopy/simple_view.rb +36 -0
- data/lib/coopy/table.rb +44 -0
- data/lib/coopy/table_comparison_state.rb +33 -0
- data/lib/coopy/table_diff.rb +634 -0
- data/lib/coopy/table_text.rb +14 -0
- data/lib/coopy/table_view.rb +31 -0
- data/lib/coopy/unit.rb +53 -0
- data/lib/coopy/version.rb +3 -0
- data/lib/coopy/view.rb +34 -0
- data/spec/fixtures/bridges.html +10 -0
- data/spec/fixtures/bridges_diff.csv +8 -0
- data/spec/fixtures/bridges_new.csv +9 -0
- data/spec/fixtures/bridges_old.csv +9 -0
- data/spec/fixtures/planetary_bodies.html +22 -0
- data/spec/fixtures/planetary_bodies_diff.csv +19 -0
- data/spec/fixtures/planetary_bodies_new.csv +20 -0
- data/spec/fixtures/planetary_bodies_old.csv +19 -0
- data/spec/fixtures/quote_me.csv +10 -0
- data/spec/fixtures/quote_me2.csv +11 -0
- data/spec/integration/table_diff_spec.rb +57 -0
- data/spec/libs/compare_flags_spec.rb +40 -0
- data/spec/libs/coopy_spec.rb +14 -0
- data/spec/libs/ordering_spec.rb +28 -0
- data/spec/libs/unit_spec.rb +31 -0
- data/spec/spec_helper.rb +29 -0
- metadata +153 -46
- data/bin/sqlite_diff +0 -4
- data/bin/sqlite_patch +0 -4
- data/bin/sqlite_rediff +0 -4
- data/lib/coopy/dbi_sql_wrapper.rb +0 -89
- data/lib/coopy/diff_apply_sql.rb +0 -35
- data/lib/coopy/diff_columns.rb +0 -33
- data/lib/coopy/diff_output.rb +0 -21
- data/lib/coopy/diff_output_action.rb +0 -34
- data/lib/coopy/diff_output_group.rb +0 -40
- data/lib/coopy/diff_output_raw.rb +0 -17
- data/lib/coopy/diff_output_stats.rb +0 -45
- data/lib/coopy/diff_output_table.rb +0 -49
- data/lib/coopy/diff_output_tdiff.rb +0 -48
- data/lib/coopy/diff_parser.rb +0 -92
- data/lib/coopy/diff_render_csv.rb +0 -29
- data/lib/coopy/diff_render_html.rb +0 -74
- data/lib/coopy/diff_render_log.rb +0 -52
- data/lib/coopy/row_change.rb +0 -25
- data/lib/coopy/scraperwiki_sql_wrapper.rb +0 -8
- data/lib/coopy/scraperwiki_utils.rb +0 -23
- data/lib/coopy/sequel_sql_wrapper.rb +0 -73
- data/lib/coopy/sql_compare.rb +0 -222
- data/lib/coopy/sql_wrapper.rb +0 -34
- data/lib/coopy/sqlite_sql_wrapper.rb +0 -143
- data/test/test_coopy.rb +0 -126
@@ -0,0 +1,72 @@
|
|
1
|
+
module Coopy
|
2
|
+
class IndexPair
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@ia = Index.new
|
6
|
+
@ib = Index.new
|
7
|
+
@quality = 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_column(i)
|
11
|
+
@ia.add_column i
|
12
|
+
@ib.add_column i
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_columns(ca, cb)
|
16
|
+
@ia.add_column ca
|
17
|
+
@ib.add_column cb
|
18
|
+
end
|
19
|
+
|
20
|
+
def index_tables(a, b)
|
21
|
+
@ia.index_table a
|
22
|
+
@ib.index_table b
|
23
|
+
# calculate
|
24
|
+
# P(present and unique within a AND present and unique with b)
|
25
|
+
# for rows in a
|
26
|
+
good = 0
|
27
|
+
@ia.items.keys.each do |key|
|
28
|
+
item_a = @ia.items[key]
|
29
|
+
spot_a = item_a.lst.length
|
30
|
+
item_b = @ib.items[key]
|
31
|
+
spot_b = 0;
|
32
|
+
spot_b = item_b.lst.length if item_b
|
33
|
+
if spot_a == 1 && spot_b == 1
|
34
|
+
good += 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
@quality = good / [1.0,a.height].max
|
38
|
+
end
|
39
|
+
|
40
|
+
def query_by_key(ka)
|
41
|
+
result = CrossMatch.new
|
42
|
+
result.item_a = @ia.items[ka]
|
43
|
+
result.item_b = @ib.items[ka]
|
44
|
+
result.spot_a = result.spot_b = 0
|
45
|
+
if ka != ""
|
46
|
+
result.spot_a = result.item_a.lst.length if result.item_a
|
47
|
+
result.spot_b = result.item_b.lst.length if result.item_b
|
48
|
+
end
|
49
|
+
result
|
50
|
+
end
|
51
|
+
|
52
|
+
def query_by_content(row)
|
53
|
+
ka = @ia.to_key_by_content(row)
|
54
|
+
query_by_key ka
|
55
|
+
end
|
56
|
+
|
57
|
+
def query_local(row)
|
58
|
+
ka = @ia.to_key(@ia.get_table,row)
|
59
|
+
query_by_key ka
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_top_freq
|
63
|
+
[@ib.top_freq, @ia.top_freq].max
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_quality
|
67
|
+
@quality
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
data/lib/coopy/mover.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
module Coopy
|
2
|
+
class Mover
|
3
|
+
|
4
|
+
def self.move_units(units)
|
5
|
+
isrc = []
|
6
|
+
idest = []
|
7
|
+
len = units.length
|
8
|
+
ltop = -1.0
|
9
|
+
rtop = -1
|
10
|
+
in_src = {}
|
11
|
+
in_dest = {}
|
12
|
+
(0..len-1).each do |i|
|
13
|
+
unit = units[i]
|
14
|
+
if (unit.l>=0 && unit.r>=0)
|
15
|
+
ltop = unit.l if (ltop<unit.l)
|
16
|
+
rtop = unit.r if (rtop<unit.r)
|
17
|
+
in_src[unit.l] = i
|
18
|
+
in_dest[unit.r] = i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
v = nil
|
22
|
+
(0...ltop+1).each do |i|
|
23
|
+
v = in_src[i]
|
24
|
+
isrc.push(v) if v
|
25
|
+
end
|
26
|
+
(0...rtop+1).each do |i|
|
27
|
+
v = in_dest[i]
|
28
|
+
idest.push(v) if v
|
29
|
+
end
|
30
|
+
return move_without_extras(isrc,idest)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.move_with_extras(isrc, idest)
|
34
|
+
# First pass: eliminate non-overlapping elements (inserts+deletes)
|
35
|
+
len = isrc.length
|
36
|
+
len2 = idest.length
|
37
|
+
in_src = {}
|
38
|
+
in_dest = {}
|
39
|
+
(0..len-1).each do |i|
|
40
|
+
in_src[isrc[i]] = i
|
41
|
+
end
|
42
|
+
(0..len2-1).each do |i|
|
43
|
+
in_dest[idest[i]] = i
|
44
|
+
end
|
45
|
+
src = []
|
46
|
+
dest = []
|
47
|
+
v = nil
|
48
|
+
(0..len-1).each do |i|
|
49
|
+
v = isrc[i]
|
50
|
+
src << v if (in_dest.has_key?(v))
|
51
|
+
end
|
52
|
+
(0..len2-1).each do |i|
|
53
|
+
v = idest[i]
|
54
|
+
dest << v if (in_src.has_key?(v))
|
55
|
+
end
|
56
|
+
return move_without_extras(src,dest)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.move_without_extras(src, dest)
|
60
|
+
return nil if (src.length!=dest.length)
|
61
|
+
return [] if (src.length<=1)
|
62
|
+
|
63
|
+
len = src.length
|
64
|
+
in_src = {}
|
65
|
+
blk_len = {}
|
66
|
+
blk_src_loc = {}
|
67
|
+
blk_dest_loc = {}
|
68
|
+
(0...len).each do |i|
|
69
|
+
in_src[src[i]] = i
|
70
|
+
end
|
71
|
+
ct = 0
|
72
|
+
in_cursor = -2
|
73
|
+
out_cursor = 0
|
74
|
+
nxt = nil
|
75
|
+
blk = -1
|
76
|
+
v = nil
|
77
|
+
while (out_cursor<len)
|
78
|
+
v = dest[out_cursor]
|
79
|
+
nxt = in_src[v]
|
80
|
+
if (nxt != in_cursor+1)
|
81
|
+
blk = v
|
82
|
+
ct = 1
|
83
|
+
blk_src_loc[blk] = nxt
|
84
|
+
blk_dest_loc[blk] = out_cursor
|
85
|
+
else
|
86
|
+
ct+=1
|
87
|
+
end
|
88
|
+
blk_len[blk] = ct
|
89
|
+
in_cursor = nxt
|
90
|
+
out_cursor+=1
|
91
|
+
end
|
92
|
+
|
93
|
+
blks = blk_len.keys
|
94
|
+
blks.sort!{ |a,b| blk_len[a] <=> blk_len[b] }
|
95
|
+
|
96
|
+
moved = []
|
97
|
+
|
98
|
+
while (blks.length>0)
|
99
|
+
blk = blks.shift
|
100
|
+
blen = blks.length
|
101
|
+
ref_src_loc = blk_src_loc[blk]
|
102
|
+
ref_dest_loc = blk_dest_loc[blk]
|
103
|
+
i = blen-1
|
104
|
+
while (i>=0)
|
105
|
+
blki = blks[i]
|
106
|
+
blki_src_loc = blk_src_loc[blki]
|
107
|
+
to_left_src = blki_src_loc < ref_src_loc
|
108
|
+
to_left_dest = blk_dest_loc[blki] < ref_dest_loc
|
109
|
+
if (to_left_src!=to_left_dest)
|
110
|
+
ct = blk_len[blki]
|
111
|
+
(0..ct-1).each do |j|
|
112
|
+
moved.push(src[blki_src_loc])
|
113
|
+
blki_src_loc+=1
|
114
|
+
end
|
115
|
+
blks.splice(i,1)
|
116
|
+
end
|
117
|
+
i-=1
|
118
|
+
end
|
119
|
+
end
|
120
|
+
return moved
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Coopy
|
2
|
+
class Ordering
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@order = []
|
6
|
+
@ignore_parent = false
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(l, r, p = -2)
|
10
|
+
p = -2 if @ignore_parent
|
11
|
+
@order << Coopy::Unit.new(l,r,p)
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_list
|
15
|
+
@order
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
@order.map{|x| x.to_s}.join(", ")
|
20
|
+
end
|
21
|
+
|
22
|
+
def ignore_parent
|
23
|
+
@ignore_parent = true;
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/coopy/row.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
module Coopy
|
2
|
+
class SimpleTable
|
3
|
+
|
4
|
+
include Coopy::Table
|
5
|
+
|
6
|
+
def initialize(w, h)
|
7
|
+
@data = {} # Map<Int,Dynamic>
|
8
|
+
@width = w
|
9
|
+
@height = h
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_table
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_accessor :size
|
17
|
+
|
18
|
+
def get_size
|
19
|
+
@height
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_cell(x, y)
|
23
|
+
@data[x+y*@width]
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_cell(x, y, c)
|
27
|
+
@data[x+y*@width] = c
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
table_to_string(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def table_to_string(tab)
|
35
|
+
x = ""
|
36
|
+
(0..tab.height-1).each do |i|
|
37
|
+
(0..tab.width-1).each do |j|
|
38
|
+
x += " " if (j>0)
|
39
|
+
x += tab.get_cell(j,i).to_s
|
40
|
+
end
|
41
|
+
x += "\n"
|
42
|
+
end
|
43
|
+
return x
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_cell_view
|
47
|
+
Coopy::SimpleView.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_resizable?
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
def resize(w, h)
|
55
|
+
@width = w
|
56
|
+
@height = h
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
def clear
|
61
|
+
@data = {}
|
62
|
+
end
|
63
|
+
|
64
|
+
def insert_or_delete_rows(fate, hfate)
|
65
|
+
data2 = {}
|
66
|
+
(0..fate.length-1).each do |i|
|
67
|
+
j = fate[i]
|
68
|
+
if (j!=-1)
|
69
|
+
(0..@width-1).each do |c|
|
70
|
+
idx = i*@width+c;
|
71
|
+
idxf (@data.has_key?(idx))
|
72
|
+
data2[j*@width+c] = @data.get(idx)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
@h = hfate
|
77
|
+
@data = data2
|
78
|
+
return true
|
79
|
+
end
|
80
|
+
|
81
|
+
def insert_or_delete_columns(fate, wfate)
|
82
|
+
data2 = {}
|
83
|
+
(0..fate.length-1).each do |i|
|
84
|
+
j = fate[i]
|
85
|
+
if (j!=-1)
|
86
|
+
(0..@height-1).each do |r|
|
87
|
+
idx = r*@width+i
|
88
|
+
if (data.has_key?(idx))
|
89
|
+
data2[r*wfate+j] = data.get(idx)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
@width = wfate
|
95
|
+
@data = data2
|
96
|
+
return true
|
97
|
+
end
|
98
|
+
|
99
|
+
def trim_blank
|
100
|
+
return true if (h==0)
|
101
|
+
h_test = @height
|
102
|
+
h_test = 3 if (h_test>=3)
|
103
|
+
view = get_cell_view
|
104
|
+
space = view.to_datum("")
|
105
|
+
more = true
|
106
|
+
while (more)
|
107
|
+
(0..width-1).each do |i|
|
108
|
+
c = get_cell(i,@height-1)
|
109
|
+
if (!(view.equals(c,space)||c==nil))
|
110
|
+
more = false
|
111
|
+
break
|
112
|
+
end
|
113
|
+
end
|
114
|
+
h-=1 if (more)
|
115
|
+
end
|
116
|
+
more = true
|
117
|
+
nw = @width
|
118
|
+
while (more)
|
119
|
+
break if (@width==0)
|
120
|
+
(0..h_test-1).each do |i|
|
121
|
+
c = get_cell(nw-1,i)
|
122
|
+
if (!(view.equals(c,space)||c==nil))
|
123
|
+
more = false
|
124
|
+
break
|
125
|
+
end
|
126
|
+
end
|
127
|
+
nw -=1 if (more)
|
128
|
+
end
|
129
|
+
return true if (nw==w)
|
130
|
+
data2 = {}
|
131
|
+
(0..nw-1).each do |i|
|
132
|
+
(0..h-1).each do |r|
|
133
|
+
idx = r*@width+i;
|
134
|
+
if (@data.exists(idx))
|
135
|
+
data2[r*nw+i] = @data.get(idx)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
@width = nw
|
140
|
+
@data = data2
|
141
|
+
return true
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Coopy
|
2
|
+
class SimpleView
|
3
|
+
|
4
|
+
include Coopy::View
|
5
|
+
|
6
|
+
def to_s(d)
|
7
|
+
return nil if (d==nil)
|
8
|
+
return d.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_bag(d)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_table(d)
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def has_structure(d)
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def equals(d1, d2)
|
24
|
+
#trace("Comparing " + d1 + " and " + d2 + " -- " + (("" + d1) == ("" + d2)));
|
25
|
+
return true if (d1==nil && d2==nil)
|
26
|
+
return true if (d1==nil && d2.to_s=="")
|
27
|
+
return true if (d1.to_s=="" && d2==nil)
|
28
|
+
return d1.to_s == d2.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_datum(str)
|
32
|
+
return nil if (str==nil)
|
33
|
+
return SimpleCell.new(str)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/coopy/table.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Coopy
|
2
|
+
module Table
|
3
|
+
|
4
|
+
attr_reader :height # integer
|
5
|
+
attr_reader :width # integer
|
6
|
+
|
7
|
+
def get_cell(x, y)
|
8
|
+
raise NotImplementedError
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_cell(x, y, cell)
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_cell_view
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def is_resizable?
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def resize(w, h)
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def clear
|
28
|
+
raise NotImplementedError
|
29
|
+
end
|
30
|
+
|
31
|
+
def insert_or_delete_rows(fate, hfate)
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
def insert_or_delete_columns(fate, wfate)
|
36
|
+
raise NotImplementedError
|
37
|
+
end
|
38
|
+
|
39
|
+
def trim_blank
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|