rbrainz 0.1.1 → 0.2.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.
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',