rets 0.4.0 → 0.5.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.
- data/CHANGELOG.md +9 -0
- data/Manifest.txt +0 -1
- data/Rakefile +7 -1
- data/bin/rets +13 -5
- data/lib/rets.rb +32 -11
- data/lib/rets/client.rb +110 -299
- data/lib/rets/metadata/resource.rb +1 -1
- data/lib/rets/metadata/table.rb +1 -0
- data/lib/rets/parser/compact.rb +11 -1
- data/lib/rets/parser/multipart.rb +11 -12
- data/test/fixtures.rb +12 -0
- data/test/helper.rb +4 -4
- data/test/test_client.rb +29 -431
- data/test/test_locking_http_client.rb +29 -0
- data/test/test_metadata.rb +7 -2
- data/test/test_parser_compact.rb +13 -3
- data/test/test_parser_multipart.rb +5 -5
- metadata +17 -11
- data/lib/rets/authentication.rb +0 -57
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
class TestLockingHttpClient < MiniTest::Test
|
4
|
+
def setup
|
5
|
+
@fake_client = stub('fake_client')
|
6
|
+
@locker = stub('locker')
|
7
|
+
@locking_client = Rets::LockingHttpClient.new(@fake_client, @locker, 'lock_name')
|
8
|
+
@url = "fake rets url"
|
9
|
+
@params = {'fake_param' => 'fake_param_value'}
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_locking_client_calls_the_real_client_if_lock_succeeds
|
13
|
+
@locker.stubs(:lock).with('lock_name', {}).yields(nil)
|
14
|
+
@fake_client.expects(:http_post).with(@url, @params, {})
|
15
|
+
@locking_client.http_post(@url, @params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_locking_client_does_nothing_if_lock_fails_to_yield
|
19
|
+
@fake_client.expects(:http_post).never
|
20
|
+
@locker.stubs(:lock).with('lock_name', {})
|
21
|
+
@locking_client.http_post(@url, @params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_locking_client_returns_result_from_client
|
25
|
+
@fake_client.stubs(:http_post).returns('result')
|
26
|
+
@locker.stubs(:lock).with('lock_name', {}).yields(nil)
|
27
|
+
assert_equal 'result', @locking_client.http_post(@url, @params)
|
28
|
+
end
|
29
|
+
end
|
data/test/test_metadata.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
|
-
|
1
|
+
require_relative "helper"
|
2
2
|
|
3
|
-
class TestMetadata < Test
|
3
|
+
class TestMetadata < MiniTest::Test
|
4
4
|
def setup
|
5
5
|
@root = Rets::Metadata::Root.new
|
6
|
+
$VERBOSE = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
$VERBOSE = false
|
6
11
|
end
|
7
12
|
|
8
13
|
def test_metadata_root_fetch_sources_returns_hash_of_metadata_types
|
data/test/test_parser_compact.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
require_relative "helper"
|
2
2
|
|
3
|
-
class TestParserCompact < Test
|
3
|
+
class TestParserCompact < MiniTest::Test
|
4
4
|
def test_parse_document_raises_on_invalid_delimiter
|
5
|
-
|
5
|
+
assert_raises Rets::Parser::Compact::InvalidDelimiter do
|
6
6
|
Rets::Parser::Compact.parse_document(INVALID_DELIMETER)
|
7
7
|
end
|
8
8
|
end
|
@@ -56,6 +56,16 @@ class TestParserCompact < Test::Unit::TestCase
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
def test_parse_empty_document
|
60
|
+
rows = Rets::Parser::Compact.parse_document(EMPTY_COMPACT)
|
61
|
+
assert_equal [], rows
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_get_count
|
65
|
+
count = Rets::Parser::Compact.get_count(COUNT_ONLY)
|
66
|
+
assert_equal 1234, count
|
67
|
+
end
|
68
|
+
|
59
69
|
def test_parse_example
|
60
70
|
rows = Rets::Parser::Compact.parse_document(Nokogiri.parse(SAMPLE_COMPACT))
|
61
71
|
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
1
|
+
require_relative "helper"
|
2
2
|
|
3
|
-
class TestParserMultipart < Test
|
3
|
+
class TestParserMultipart < MiniTest::Test
|
4
4
|
def test_parse_returns_multiple_parts
|
5
5
|
headers = {"content-type"=>"image/jpeg", "content-id"=>"90020062739", "content-length"=>"10"}
|
6
6
|
|
@@ -18,12 +18,12 @@ class TestParserMultipart < Test::Unit::TestCase
|
|
18
18
|
assert_equal headers.merge("object-id" => "2"), part.headers
|
19
19
|
assert_equal "yyyyyyyy", part.body.strip
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def test_parse_real_mls_data
|
23
23
|
parts = Rets::Parser::Multipart.parse(MULTIPART_RESPONSE_URLS, "rets.object.content.boundary.1330546052739")
|
24
24
|
assert_equal 5, parts.size
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def test_parse_values_with_colon_data
|
28
28
|
parts = Rets::Parser::Multipart.parse(MULTIPART_RESPONSE_URLS, "rets.object.content.boundary.1330546052739")
|
29
29
|
assert_equal 'http://foobarmls.com/RETS//MediaDisplay/98/hr2890998-1.jpg', parts[0].headers['location']
|
@@ -32,7 +32,7 @@ class TestParserMultipart < Test::Unit::TestCase
|
|
32
32
|
def test_parse_with_error
|
33
33
|
raw = "\r\n--89467f8e0c6b48158c8f1883910212ec\r\nContent-Type: text/xml\r\nContent-ID: foo\r\nObject-ID: *\r\n\r\n<RETS ReplyCode=\"20403\" ReplyText=\"No Object Found\" />\r\n\r\n--89467f8e0c6b48158c8f1883910212ec--\r\n"
|
34
34
|
boundary = "89467f8e0c6b48158c8f1883910212ec"
|
35
|
-
|
35
|
+
assert_raises Rets::InvalidRequest do
|
36
36
|
Rets::Parser::Multipart.parse(raw, boundary)
|
37
37
|
end
|
38
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,16 +9,16 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-09-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: httpclient
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 2.3.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 2.3.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: nokogiri
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '4.0'
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '4.0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: mocha
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,7 +114,7 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '3.
|
117
|
+
version: '3.6'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
requirements:
|
123
123
|
- - ~>
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: '3.
|
125
|
+
version: '3.6'
|
126
126
|
description: ! '[](http://travis-ci.org/estately/rets)
|
127
127
|
|
128
128
|
A pure-ruby library for fetching data from [RETS] servers.
|
@@ -135,7 +135,9 @@ executables:
|
|
135
135
|
- rets
|
136
136
|
extensions: []
|
137
137
|
extra_rdoc_files:
|
138
|
+
- CHANGELOG.md
|
138
139
|
- Manifest.txt
|
140
|
+
- README.md
|
139
141
|
files:
|
140
142
|
- CHANGELOG.md
|
141
143
|
- Manifest.txt
|
@@ -143,7 +145,6 @@ files:
|
|
143
145
|
- Rakefile
|
144
146
|
- bin/rets
|
145
147
|
- lib/rets.rb
|
146
|
-
- lib/rets/authentication.rb
|
147
148
|
- lib/rets/client.rb
|
148
149
|
- lib/rets/metadata.rb
|
149
150
|
- lib/rets/metadata/containers.rb
|
@@ -160,6 +161,7 @@ files:
|
|
160
161
|
- test/test_metadata.rb
|
161
162
|
- test/test_parser_compact.rb
|
162
163
|
- test/test_parser_multipart.rb
|
164
|
+
- test/test_locking_http_client.rb
|
163
165
|
- .gemtest
|
164
166
|
homepage: http://github.com/estately/rets
|
165
167
|
licenses: []
|
@@ -175,6 +177,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
175
177
|
- - ! '>='
|
176
178
|
- !ruby/object:Gem::Version
|
177
179
|
version: '0'
|
180
|
+
segments:
|
181
|
+
- 0
|
182
|
+
hash: -2023944965655718483
|
178
183
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
184
|
none: false
|
180
185
|
requirements:
|
@@ -183,13 +188,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
188
|
version: '0'
|
184
189
|
requirements: []
|
185
190
|
rubyforge_project: rets
|
186
|
-
rubygems_version: 1.8.
|
191
|
+
rubygems_version: 1.8.23
|
187
192
|
signing_key:
|
188
193
|
specification_version: 3
|
189
194
|
summary: ! '[](http://travis-ci.org/estately/rets)
|
190
195
|
A pure-ruby library for fetching data from [RETS] servers'
|
191
196
|
test_files:
|
192
197
|
- test/test_client.rb
|
198
|
+
- test/test_locking_http_client.rb
|
193
199
|
- test/test_metadata.rb
|
194
200
|
- test/test_parser_compact.rb
|
195
201
|
- test/test_parser_multipart.rb
|
data/lib/rets/authentication.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module Rets
|
2
|
-
# Adapted from dbrain's Net::HTTP::DigestAuth gem, and RETS4R auth
|
3
|
-
# in order to support RETS' usage of digest authentication.
|
4
|
-
module Authentication
|
5
|
-
def build_auth(digest_authenticate, uri, nc = 0, method = "POST")
|
6
|
-
user = CGI.unescape uri.user
|
7
|
-
password = CGI.unescape uri.password
|
8
|
-
|
9
|
-
digest_authenticate =~ /^(\w+) (.*)/
|
10
|
-
|
11
|
-
params = {}
|
12
|
-
$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
|
13
|
-
|
14
|
-
cnonce = Digest::MD5.hexdigest "%x" % (Time.now.to_i + rand(65535))
|
15
|
-
|
16
|
-
digest = calculate_digest(
|
17
|
-
user, password, params['realm'], params['nonce'], method, uri.request_uri, params['qop'], cnonce, nc
|
18
|
-
)
|
19
|
-
|
20
|
-
header = [
|
21
|
-
%Q(Digest username="#{user}"),
|
22
|
-
%Q(realm="#{params['realm']}"),
|
23
|
-
%Q(qop="#{params['qop']}"),
|
24
|
-
%Q(uri="#{uri.request_uri}"),
|
25
|
-
%Q(nonce="#{params['nonce']}"),
|
26
|
-
%Q(nc=#{('%08x' % nc)}),
|
27
|
-
%Q(cnonce="#{cnonce}"),
|
28
|
-
%Q(response="#{digest}"),
|
29
|
-
%Q(opaque="#{params['opaque']}"),
|
30
|
-
]
|
31
|
-
|
32
|
-
header.join(", ")
|
33
|
-
end
|
34
|
-
|
35
|
-
def calculate_digest(user, password, realm, nonce, method, uri, qop, cnonce, nc)
|
36
|
-
a1 = Digest::MD5.hexdigest "#{user}:#{realm}:#{password}"
|
37
|
-
a2 = Digest::MD5.hexdigest "#{method}:#{uri}"
|
38
|
-
|
39
|
-
if qop
|
40
|
-
Digest::MD5.hexdigest("#{a1}:#{nonce}:#{'%08x' % nc}:#{cnonce}:#{qop}:#{a2}")
|
41
|
-
else
|
42
|
-
Digest::MD5.hexdigest("#{a1}:#{nonce}:#{a2}")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def calculate_user_agent_digest(product, user_agent_password, rets_request_id, session_id, version)
|
47
|
-
a1 = Digest::MD5.hexdigest "#{product}:#{user_agent_password}"
|
48
|
-
|
49
|
-
Digest::MD5.hexdigest "#{a1}:#{rets_request_id}:#{session_id}:#{version}"
|
50
|
-
end
|
51
|
-
|
52
|
-
def build_user_agent_auth(*args)
|
53
|
-
%Q(Digest #{calculate_user_agent_digest(*args)})
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|