rbrainz 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/CHANGES +31 -0
  2. data/LICENSE +1 -1
  3. data/README +3 -2
  4. data/Rakefile +40 -22
  5. data/TODO +6 -23
  6. data/doc/README.rdoc +50 -21
  7. data/examples/getartist.rb +6 -4
  8. data/examples/getuser.rb +30 -0
  9. data/examples/searchartists.rb +35 -0
  10. data/lib/rbrainz.rb +12 -7
  11. data/lib/rbrainz/core_ext.rb +8 -0
  12. data/lib/rbrainz/core_ext/mbid.rb +30 -0
  13. data/lib/rbrainz/core_ext/net_http_digest.rb +52 -0
  14. data/lib/rbrainz/core_ext/range.rb +28 -0
  15. data/lib/rbrainz/core_ext/range/equality.rb +232 -0
  16. data/lib/rbrainz/data/countrynames.rb +7 -5
  17. data/lib/rbrainz/data/languagenames.rb +8 -5
  18. data/lib/rbrainz/data/releasetypenames.rb +34 -0
  19. data/lib/rbrainz/data/scriptnames.rb +8 -5
  20. data/lib/rbrainz/model.rb +27 -35
  21. data/lib/rbrainz/model/alias.rb +31 -7
  22. data/lib/rbrainz/model/artist.rb +30 -41
  23. data/lib/rbrainz/model/collection.rb +102 -0
  24. data/lib/rbrainz/model/default_factory.rb +78 -0
  25. data/lib/rbrainz/model/disc.rb +45 -8
  26. data/lib/rbrainz/model/entity.rb +122 -53
  27. data/lib/rbrainz/model/incomplete_date.rb +31 -47
  28. data/lib/rbrainz/model/individual.rb +103 -0
  29. data/lib/rbrainz/model/label.rb +42 -33
  30. data/lib/rbrainz/model/mbid.rb +111 -40
  31. data/lib/rbrainz/model/relation.rb +78 -14
  32. data/lib/rbrainz/model/release.rb +119 -31
  33. data/lib/rbrainz/model/release_event.rb +38 -9
  34. data/lib/rbrainz/model/scored_collection.rb +99 -0
  35. data/lib/rbrainz/model/tag.rb +39 -0
  36. data/lib/rbrainz/model/track.rb +37 -13
  37. data/lib/rbrainz/model/user.rb +48 -0
  38. data/lib/rbrainz/utils.rb +9 -0
  39. data/lib/rbrainz/utils/data.rb +78 -0
  40. data/lib/rbrainz/utils/helper.rb +22 -0
  41. data/lib/rbrainz/version.rb +15 -0
  42. data/lib/rbrainz/webservice.rb +32 -6
  43. data/lib/rbrainz/webservice/filter.rb +124 -47
  44. data/lib/rbrainz/webservice/includes.rb +49 -10
  45. data/lib/rbrainz/webservice/mbxml.rb +228 -173
  46. data/lib/rbrainz/webservice/query.rb +312 -25
  47. data/lib/rbrainz/webservice/webservice.rb +164 -27
  48. data/test/lib/mock_webservice.rb +53 -0
  49. data/test/lib/test_entity.rb +27 -8
  50. data/test/lib/test_factory.rb +47 -0
  51. data/test/lib/testing_helper.rb +7 -5
  52. data/test/test-data/invalid/artist/tags_1.xml +6 -0
  53. data/test/test-data/valid/artist/Tchaikovsky-2.xml +12 -0
  54. data/test/test-data/valid/label/Atlantic_Records_2.xml +3 -0
  55. data/test/test-data/valid/label/Atlantic_Records_3.xml +11 -0
  56. data/test/test-data/valid/release/Highway_61_Revisited_2.xml +12 -0
  57. data/test/test-data/valid/track/Silent_All_These_Years_6.xml +8 -0
  58. data/test/test_alias.rb +13 -7
  59. data/test/test_artist.rb +26 -4
  60. data/test/test_artist_filter.rb +11 -6
  61. data/test/test_artist_includes.rb +11 -6
  62. data/test/test_collection.rb +66 -0
  63. data/test/test_default_factory.rb +75 -0
  64. data/test/test_disc.rb +9 -4
  65. data/test/test_incomplete_date.rb +21 -14
  66. data/test/test_label.rb +56 -18
  67. data/test/test_label_filter.rb +10 -5
  68. data/test/test_label_includes.rb +11 -6
  69. data/test/test_mbid.rb +34 -19
  70. data/test/test_mbxml.rb +242 -72
  71. data/test/test_query.rb +92 -7
  72. data/test/test_range_equality.rb +144 -0
  73. data/test/test_relation.rb +18 -7
  74. data/test/test_release.rb +15 -4
  75. data/test/test_release_event.rb +16 -4
  76. data/test/test_release_filter.rb +11 -5
  77. data/test/test_release_includes.rb +11 -6
  78. data/test/test_scored_collection.rb +86 -0
  79. data/test/test_tag.rb +39 -0
  80. data/test/test_track.rb +15 -4
  81. data/test/test_track_filter.rb +11 -5
  82. data/test/test_track_includes.rb +11 -6
  83. data/test/test_utils.rb +41 -0
  84. data/test/test_webservice.rb +16 -17
  85. metadata +93 -57
@@ -0,0 +1,8 @@
1
+ # $Id: core_ext.rb 132 2007-07-12 19:55:52Z phw $
2
+ #
3
+ # Author:: Nigel Graham (mailto:nigel_graham@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
7
+
8
+ Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].each { |file| require(file) }
@@ -0,0 +1,30 @@
1
+ # $Id: mbid.rb 148 2007-07-19 17:26:33Z phw $
2
+ #
3
+ # Core extensions to add a to_mbid conversion to existing classes.
4
+ #
5
+ # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
6
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
7
+ # License:: RBrainz is free software distributed under a BSD style license.
8
+ # See LICENSE[file:../LICENSE.html] for permissions.
9
+
10
+ #
11
+ class String
12
+ # Convert a string into a MusicBrainz::Model::MBID object of the given type.
13
+ #
14
+ # Raises:: MusicBrainz::Model::EntityTypeNotMatchingError
15
+ def to_mbid(entity_type=nil)
16
+ ::MusicBrainz::Model::MBID.new(self, entity_type)
17
+ end
18
+ end
19
+
20
+ #
21
+ module URI #:nodoc:
22
+ class HTTP
23
+ # Create a MusicBrainz::Model::MBID from a HTTP object of the given type.
24
+ #
25
+ # Raises:: MusicBrainz::Model::EntityTypeNotMatchingError
26
+ def to_mbid(entity_type=nil)
27
+ ::MusicBrainz::Model::MBID.new(self.to_s, entity_type)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,52 @@
1
+ # $Id: net_http_digest.rb 136 2007-07-16 15:45:32Z phw $
2
+ #
3
+ # Author:: Nigel Graham (mailto:nigel_graham@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
7
+ # Notes:: Based on http://textsnippets.com/posts/show/1075 and
8
+ # http://segment7.net/projects/ruby/snippets/digest_auth.rb
9
+
10
+ require 'digest/md5'
11
+ require 'net/http'
12
+
13
+ module Net # :nodoc:
14
+ module HTTPHeader # :nodoc:
15
+ @@nonce_count = -1
16
+ CNONCE = Digest::MD5.new.update("%x" % (Time.now.to_i + rand(65535))).hexdigest
17
+ def digest_auth(user, password, response)
18
+ @@nonce_count += 1
19
+
20
+ response['www-authenticate'] =~ /^(\w+) (.*)/
21
+
22
+ params = {}
23
+ $2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
24
+
25
+ a_1 = "#{user}:#{params['realm']}:#{password}"
26
+ a_2 = "#{@method}:#{@path}"
27
+ request_digest = ''
28
+ request_digest << Digest::MD5.new.update(a_1).hexdigest
29
+ request_digest << ':' << params['nonce']
30
+ if params['qop']
31
+ request_digest << ':' << ('%08x' % @@nonce_count)
32
+ request_digest << ':' << CNONCE
33
+ request_digest << ':' << params['qop']
34
+ end
35
+ request_digest << ':' << Digest::MD5.new.update(a_2).hexdigest
36
+
37
+ header = []
38
+ header << "Digest username=\"#{user}\""
39
+ header << "realm=\"#{params['realm']}\""
40
+
41
+ header << "qop=#{params['qop']}" if params['qop']
42
+
43
+ header << "algorithm=MD5"
44
+ header << "uri=\"#{@path}\""
45
+ header << "nonce=\"#{params['nonce']}\""
46
+ header << "nc=#{'%08x' % @@nonce_count}" if params['qop']
47
+ header << "cnonce=\"#{CNONCE}\"" if params['qop']
48
+ header << "response=\"#{Digest::MD5.new.update(request_digest).hexdigest}\""
49
+ @header['Authorization'] = header
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,28 @@
1
+ # $Id: range.rb 136 2007-07-16 15:45:32Z phw $
2
+ #
3
+ # Author:: Nigel Graham (mailto:nigel_graham@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
7
+
8
+ require File.dirname(__FILE__) + '/range/equality'
9
+
10
+ class Range #:nodoc:
11
+ include MusicBrainz::CoreExtensions::Range::Equality
12
+
13
+ alias :old_eql? :eql?
14
+ def eql?(b)
15
+ if b.kind_of? ::Range
16
+ self.begin == b.begin && self.open_end == b.open_end
17
+ else
18
+ self.begin == b && self.open_end == b.succ
19
+ end
20
+ end
21
+ remove_method :==
22
+ alias :== :eql?
23
+
24
+ alias :old_include? :include?
25
+ def include?(b)
26
+ self.started_by?(b) || self.contains?(b) || self.eql?(b) || self.finished_by?(b)
27
+ end
28
+ end
@@ -0,0 +1,232 @@
1
+ # $Id: equality.rb 137 2007-07-17 08:00:06Z phw $
2
+ #
3
+ # Author:: Nigel Graham (mailto:nigel_graham@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
7
+
8
+ module MusicBrainz
9
+ module CoreExtensions # :nodoc:
10
+ module Range #:nodoc:
11
+
12
+ ##
13
+ # Mixin module with equality operations for ranges.
14
+ # The built-in Range class is currently missing functions to compare a
15
+ # Range with another Range. There exist 13 disjoint equality operations for ranges.
16
+ # This mixin implements them all and a few extra operations for commonly used combinations.
17
+ #
18
+ module Equality
19
+
20
+ # <tt>a.before?(b)</tt> is true, if _a_ ends before the beginning of _b_.
21
+ # Same as <tt>b.after?(a)</tt>.
22
+ #
23
+ # |A------|
24
+ # |B------|
25
+ def before?(b)
26
+ if b.kind_of? ::Range
27
+ self.open_end < b.begin
28
+ else
29
+ self.open_end < b
30
+ end
31
+ end
32
+ alias :< :before?
33
+
34
+ # <tt>a.after?(b)</tt> is true, if _a_ begins after the end of _b_.
35
+ # Same as <tt>b.before?(a)</tt>.
36
+ #
37
+ # |A------|
38
+ # |B------|
39
+ def after?(b)
40
+ if b.kind_of? ::Range
41
+ b.open_end < self.begin
42
+ else
43
+ b.succ < self.begin
44
+ end
45
+ end
46
+ alias :> :after?
47
+
48
+ =begin comment
49
+ Allready exists in Range so we can't define it in the module
50
+ def eql?(b)
51
+ if b.kind_of? ::Range
52
+ puts "Range class eql?"
53
+ self.begin == b.begin && self.open_end == b.open_end
54
+ else
55
+ puts "b.class eql?"
56
+ self.begin == b && self.open_end == b.succ
57
+ end
58
+ end
59
+ alias :== :eql?
60
+ =end
61
+
62
+ # <tt>a.meets_beginning_of?(b)</tt> is true, if _b_ begins exactly at the end of _a_.
63
+ # Same as <tt>b.meets_end_of?(a)</tt>.
64
+ #
65
+ # |A------|
66
+ # |B------|
67
+ def meets_beginning_of?(b)
68
+ if b.kind_of? ::Range
69
+ self.open_end == b.begin
70
+ else
71
+ self.open_end == b
72
+ end
73
+ end
74
+
75
+ # <tt>a.meets_end_of?(b)</tt> is true, if _b_ ends exactly at the beginning of _a_.
76
+ # Same as <tt>b.meets_beginning_of?(a)</tt>.
77
+ #
78
+ # |A------|
79
+ # |B------|
80
+ def meets_end_of?(b)
81
+ if b.kind_of? ::Range
82
+ b.open_end == self.begin
83
+ else
84
+ b.succ == self.begin
85
+ end
86
+ end
87
+
88
+ # <tt>a.overlaps_beginning_of?(b)</tt> is true, if _a_ overlaps the beginning of _b_.
89
+ # Same as <tt>b.overlaps_end_of?(a)</tt>.
90
+ #
91
+ # |A------|
92
+ # |B------|
93
+ def overlaps_beginning_of?(b)
94
+ if b.kind_of? ::Range
95
+ self.begin < b.begin && self.open_end < b.open_end && b.begin < self.open_end
96
+ else
97
+ false
98
+ end
99
+ end
100
+
101
+ # <tt>a.overlaps_end_of?(b)</tt> is true, if _a_ overlaps the end of _b_.
102
+ # Same as <tt>b.overlaps_beginning_of?(a)</tt>.
103
+ #
104
+ # |A------|
105
+ # |B------|
106
+ def overlaps_end_of?(b)
107
+ if b.kind_of? ::Range
108
+ b.begin < self.begin && b.open_end < self.open_end && self.begin < b.open_end
109
+ else
110
+ false
111
+ end
112
+ end
113
+
114
+ # <tt>a.during?(b)</tt> is true, if _a_ fits completely into _b_.
115
+ # Same as <tt>b.contains?(a)</tt>.
116
+ #
117
+ # |A------|
118
+ # |B------------|
119
+ def during?(b)
120
+ if b.kind_of? ::Range
121
+ b.begin < self.begin && self.open_end < b.open_end
122
+ else
123
+ false
124
+ end
125
+ end
126
+
127
+ # <tt>a.contains?(b)</tt> is true, if _b_ fits completely into _a_.
128
+ # Same as <tt>b.during?(a)</tt>.
129
+ #
130
+ # |A------------|
131
+ # |B------|
132
+ def contains?(b)
133
+ if b.kind_of? ::Range
134
+ self.begin < b.begin && b.open_end < self.open_end
135
+ else
136
+ self.begin < b && b.succ < self.open_end
137
+ end
138
+ end
139
+
140
+ # <tt>a.starts?(b)</tt> is true, if _a_ and _b_ have the same beginning
141
+ # but _b_ lasts longer than _a_.
142
+ # Same as <tt>b.started_by?(a)</tt>.
143
+ #
144
+ # |A------|
145
+ # |B-----------|
146
+ def starts?(b)
147
+ if b.kind_of? ::Range
148
+ self.begin == b.begin && self.open_end < b.open_end
149
+ else
150
+ false
151
+ end
152
+ end
153
+
154
+ # <tt>a.started_by?(b)</tt> is true, if _a_ and _b_ have the same
155
+ # beginning but _a_ lasts longer than _b_.
156
+ # Same as <tt>b.starts?(a)</tt>.
157
+ #
158
+ # |A-----------|
159
+ # |B------|
160
+ def started_by?(b)
161
+ if b.kind_of? ::Range
162
+ b.begin == self.begin && b.open_end < self.open_end
163
+ else
164
+ b == self.begin && b.succ < self.open_end
165
+ end
166
+ end
167
+
168
+ # <tt>a.finishes?(b)</tt> is true, if _a_ and _b_ have the same
169
+ # end but _a_ begins after _b_.
170
+ # Same as <tt>b.finished_by?(a)</tt>.
171
+ #
172
+ # |A------|
173
+ # |B-----------|
174
+ def finishes?(b)
175
+ if b.kind_of? ::Range
176
+ b.begin < self.begin && self.open_end == b.open_end
177
+ else
178
+ false
179
+ end
180
+ end
181
+
182
+ # <tt>a.finished_by?(b)</tt> is true, if _a_ and _b_ have the same
183
+ # end but _b_ begins after _a_.
184
+ # Same as <tt>b.finishes?(a)</tt>.
185
+ #
186
+ # |A-----------|
187
+ # |B------|
188
+ def finished_by?(b)
189
+ if b.kind_of? ::Range
190
+ self.begin < b.begin && b.open_end == self.open_end
191
+ else
192
+ self.begin < b && b.succ == self.open_end
193
+ end
194
+ end
195
+
196
+ # <tt>a <= b</tt> is the same as
197
+ # <tt>a.before?(b) or a.meets_beginning_of?(b)</tt>
198
+ def <=(b)
199
+ self.before?(b) || self.meets_beginning_of?(b)
200
+ end
201
+
202
+ # <tt>a >= b</tt> is the same as
203
+ # <tt>a.after?(b) or a.meets_end_of?(b)</tt>
204
+ def >=(b)
205
+ self.after?(b) || self.meets_end_of?(b)
206
+ end
207
+
208
+ # <tt>a.between?(b)</tt> is the same as
209
+ # <tt>a.starts?(b) or a.during?(b) or a.finishes?(b)</tt>
210
+ def between?(b)
211
+ self.starts?(b) || self.during?(b) || self.finishes?(b)
212
+ end
213
+
214
+ =begin comment
215
+ Allready exists in Range so we can't define it in the module
216
+ def include?(b)
217
+ self.started_by?(b) || self.contains?(b) || self.eql?(b) || self.finished_by?(b)
218
+ end
219
+ =end
220
+
221
+ protected
222
+ def open_end # :nodoc:
223
+ if self.exclude_end?
224
+ self.end
225
+ else
226
+ self.end.succ
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
@@ -1,12 +1,14 @@
1
- # $Id: countrynames.rb 4 2007-05-21 02:04:26Z phw $
2
- # Copyright (c) 2007, Philipp Wolfer
3
- # All rights reserved.
4
- # See LICENSE for permissions.
1
+ # $Id: countrynames.rb 141 2007-07-17 14:21:12Z phw $
2
+ #
3
+ # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
5
7
 
6
8
  module MusicBrainz
7
9
  module Data
8
10
 
9
- # List of country names.
11
+ # See Utils#get_country_name
10
12
  COUNTRY_NAMES = {
11
13
  'BD' => 'Bangladesh',
12
14
  'BE' => 'Belgium',
@@ -1,12 +1,15 @@
1
- # $Id: languagenames.rb 4 2007-05-21 02:04:26Z phw $
2
- # Copyright (c) 2007, Philipp Wolfer
3
- # All rights reserved.
4
- # See LICENSE for permissions.
1
+ # $Id: languagenames.rb 141 2007-07-17 14:21:12Z phw $
2
+ #
3
+ # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
5
7
 
6
8
  module MusicBrainz
7
9
  module Data
8
10
 
9
- LANGUAGE_NAMES = {
11
+ # See Utils#get_language_name
12
+ LANGUAGE_NAMES = {
10
13
  'ART' => 'Artificial (Other)',
11
14
  'ROH' => 'Raeto-Romance',
12
15
  'SCO' => 'Scots',
@@ -0,0 +1,34 @@
1
+ # $Id: releasetypenames.rb 141 2007-07-17 14:21:12Z phw $
2
+ #
3
+ # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
7
+
8
+ require 'rbrainz/model/release'
9
+
10
+ module MusicBrainz
11
+ module Data
12
+
13
+ # See Utils#get_release_type_name
14
+ RELEASE_TYPE_NAMES = {
15
+ Model::Release::TYPE_ALBUM => 'Album',
16
+ Model::Release::TYPE_AUDIOBOOK => 'Audiobook',
17
+ Model::Release::TYPE_BOOTLEG => 'Bootleg',
18
+ Model::Release::TYPE_COMPILATION => 'Compilation',
19
+ Model::Release::TYPE_EP => 'EP',
20
+ Model::Release::TYPE_INTERVIEW => 'Interview',
21
+ Model::Release::TYPE_LIVE => 'Live',
22
+ Model::Release::TYPE_NONE => 'None',
23
+ Model::Release::TYPE_OFFICIAL => 'Official',
24
+ Model::Release::TYPE_OTHER => 'Other',
25
+ Model::Release::TYPE_PROMOTION => 'Promotion',
26
+ Model::Release::TYPE_PSEUDO_RELEASE => 'Pseudo-Release',
27
+ Model::Release::TYPE_REMIX => 'Remix',
28
+ Model::Release::TYPE_SINGLE => 'Single',
29
+ Model::Release::TYPE_SOUNDTRACK => 'Soundtrack',
30
+ Model::Release::TYPE_SPOKENWORD => 'Spokenword'
31
+ }
32
+
33
+ end
34
+ end
@@ -1,12 +1,15 @@
1
- # $Id: scriptnames.rb 4 2007-05-21 02:04:26Z phw $
2
- # Copyright (c) 2007, Philipp Wolfer
3
- # All rights reserved.
4
- # See LICENSE for permissions.
1
+ # $Id: scriptnames.rb 141 2007-07-17 14:21:12Z phw $
2
+ #
3
+ # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
5
7
 
6
8
  module MusicBrainz
7
9
  module Data
8
10
 
9
- scriptNames = {
11
+ # See Utils#get_script_name
12
+ SCRIPT_NAMES = {
10
13
  'Yiii' => 'Yi',
11
14
  'Tel' => 'Telug',
12
15
  'Taml' => 'Tamil',