Merge lp:~linkinpark342/exaile/fullurl into lp:exaile/0.3.3
- fullurl
- Merge into exaile-0.3.x
Proposed by
Abhishek Mukherjee
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | not available | ||||
Proposed branch: | lp:~linkinpark342/exaile/fullurl | ||||
Merge into: | lp:exaile/0.3.3 | ||||
Diff against target: | None lines | ||||
To merge this branch: | bzr merge lp:~linkinpark342/exaile/fullurl | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Adam Olsen | Approve | ||
Review via email: mp+5683@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Abhishek Mukherjee (linkinpark342) wrote : | # |
Revision history for this message
Abhishek Mukherjee (linkinpark342) wrote : | # |
Set the status to work in progress. I found a bug with unicode filenames. I'm going to hunt it down after my exams end.
Revision history for this message
Abhishek Mukherjee (linkinpark342) wrote : | # |
Bug fixed, just a ~8 character change.
Revision history for this message
Adam Olsen (arolsen) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'xl/collection.py' |
2 | --- xl/collection.py 2009-03-18 21:59:28 +0000 |
3 | +++ xl/collection.py 2009-04-13 21:34:43 +0000 |
4 | @@ -28,6 +28,7 @@ |
5 | |
6 | import os, time, os.path, shutil, logging |
7 | import gobject |
8 | +import urllib |
9 | |
10 | logger = logging.getLogger(__name__) |
11 | |
12 | @@ -504,23 +505,24 @@ |
13 | ccheck = {} # compilations dict |
14 | |
15 | count = 0 |
16 | - for folder in os.walk(self.location): |
17 | - basepath = folder[0] |
18 | - for filename in folder[2]: |
19 | + for basepath, dirnames, filenames in os.walk(self.location): |
20 | + for filename in filenames: |
21 | if self.collection: |
22 | if self.collection._scan_stopped: |
23 | self.scanning = False |
24 | return False |
25 | count += 1 |
26 | - fullpath = os.path.join(basepath, filename) |
27 | + path = os.path.abspath(os.path.join(basepath, filename)) |
28 | + fullpath = "file://" + path |
29 | |
30 | try: |
31 | trmtime = db.get_track_attr(fullpath, "modified") |
32 | - mtime = os.path.getmtime(fullpath) |
33 | + except: |
34 | + pass |
35 | + else: |
36 | + mtime = os.path.getmtime(path) |
37 | if mtime == trmtime: |
38 | continue |
39 | - except: |
40 | - pass |
41 | |
42 | tr = db.get_track_by_loc(fullpath) |
43 | if tr: |
44 | @@ -553,6 +555,7 @@ |
45 | if not os.path.exists(f): |
46 | removals.append(db.get_track_by_loc(f)) |
47 | for tr in removals: |
48 | + logging.info(u"Removing " + unicode(tr)) |
49 | db.remove(tr) |
50 | |
51 | self.scanning = False |
52 | @@ -625,8 +628,9 @@ |
53 | tr = self.collection.get_track_by_loc(loc) |
54 | if tr: |
55 | self.collection.remove(tr) |
56 | + path = common.local_file_from_url(tr.get_loc_for_io()) |
57 | try: |
58 | - os.unlink(tr.get_loc_for_io()) |
59 | + os.unlink(path) |
60 | except OSError: # file not found? |
61 | pass |
62 | except: |
63 | |
64 | === modified file 'xl/common.py' |
65 | --- xl/common.py 2008-12-28 17:58:55 +0000 |
66 | +++ xl/common.py 2009-04-13 20:21:28 +0000 |
67 | @@ -14,7 +14,7 @@ |
68 | # along with this program; if not, write to the Free Software |
69 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
70 | |
71 | -import locale, os, time, threading, urllib, re, random, string |
72 | +import locale, os, time, threading, urllib, re, random, string, urlparse |
73 | import traceback |
74 | import logging |
75 | |
76 | @@ -155,17 +155,12 @@ |
77 | text = text.replace(old, new) |
78 | return text |
79 | |
80 | -def to_url(path): |
81 | - """ |
82 | - Converts filesystem path to URL. Returns the input unchanged if it's not |
83 | - an FS path (i.e. a URL or something invalid). |
84 | - """ |
85 | - if re.search(r'^[\w]+://', path): |
86 | - return path |
87 | - try: |
88 | - return 'file://' + urllib.pathname2url(path) |
89 | - except IOError: |
90 | - return path |
91 | +def local_file_from_url(url): |
92 | + """ |
93 | + Returns a local file path based on a url |
94 | + """ |
95 | + split = urlparse.urlsplit(url) |
96 | + return urlparse.urlunsplit(('', '') + split[2:]) |
97 | |
98 | class idict(dict): |
99 | """ |
100 | |
101 | === modified file 'xl/cover.py' |
102 | --- xl/cover.py 2009-03-24 23:16:10 +0000 |
103 | +++ xl/cover.py 2009-04-13 21:42:40 +0000 |
104 | @@ -456,7 +456,7 @@ |
105 | def find_covers(self, track, limit=-1): |
106 | covers = [] |
107 | try: |
108 | - search_dir = os.path.dirname(track.get_loc()) |
109 | + search_dir = os.path.dirname(track.local_file_name()) |
110 | except AttributeError: |
111 | raise NoCoverFoundException() |
112 | |
113 | |
114 | === modified file 'xl/metadata/__init__.py' |
115 | --- xl/metadata/__init__.py 2009-03-15 04:05:49 +0000 |
116 | +++ xl/metadata/__init__.py 2009-04-13 18:38:41 +0000 |
117 | @@ -16,6 +16,7 @@ |
118 | |
119 | # do this so formats can inherit from stuff in _base |
120 | from _base import * |
121 | +import urlparse |
122 | |
123 | import asf, flac, mod, mp3, mp4, mpc, ogg, sid, speex, tta, wav, wv |
124 | |
125 | |
126 | === modified file 'xl/metadata/_base.py' |
127 | --- xl/metadata/_base.py 2009-01-13 20:22:25 +0000 |
128 | +++ xl/metadata/_base.py 2009-04-18 06:01:50 +0000 |
129 | @@ -14,6 +14,9 @@ |
130 | |
131 | import os |
132 | from xl import common |
133 | +import urlparse |
134 | +import urllib |
135 | +import urllib2 |
136 | |
137 | import logging |
138 | logger = logging.getLogger(__name__) |
139 | @@ -42,14 +45,22 @@ |
140 | """ |
141 | Loads the tags from the file. |
142 | """ |
143 | - if self.MutagenType: |
144 | - try: |
145 | - self.mutagen = self.MutagenType(self.loc) |
146 | - except: |
147 | - logger.error("Couldn't read tags from possibly corrupt " \ |
148 | - "file %s" % self.loc) |
149 | - #common.log_exception(logger) |
150 | - raise NotReadable |
151 | + try: |
152 | + self.url = urllib2.urlopen(self.loc) |
153 | + except urllib2.URLError, urllib2.HTTPError: |
154 | + logger.error("Couldn't open url to file %s" % self.loc) |
155 | + raise NotReadable |
156 | + loc = urlparse.urlsplit(self.loc) |
157 | + if loc[0] == "file": |
158 | + if self.MutagenType: |
159 | + file_loc = common.local_file_from_url(self.loc) |
160 | + try: |
161 | + self.mutagen = self.MutagenType(file_loc) |
162 | + except: |
163 | + logger.error("Couldn't read tags from possibly corrupt " \ |
164 | + "file %s" % file_loc) |
165 | + #common.log_exception(logger) |
166 | + raise NotReadable |
167 | |
168 | def save(self): |
169 | """ |
170 | @@ -62,7 +73,8 @@ |
171 | if self.MutagenType: |
172 | return self.mutagen |
173 | else: |
174 | - return {'title':os.path.split(self.loc)[-1]} |
175 | + path = common.local_file_from_url(self.loc) |
176 | + return {'title':os.path.split(path)[-1]} |
177 | |
178 | def _get_tag(self, raw, tag): |
179 | try: |
180 | |
181 | === modified file 'xl/player.py' |
182 | --- xl/player.py 2009-04-14 18:39:32 +0000 |
183 | +++ xl/player.py 2009-04-18 06:01:50 +0000 |
184 | @@ -22,7 +22,7 @@ |
185 | |
186 | from xl import common, event, playlist, settings |
187 | import random, time, os, logging, urllib |
188 | -from urlparse import urlparse |
189 | +import urlparse |
190 | |
191 | |
192 | try: |
193 | @@ -446,10 +446,13 @@ |
194 | |
195 | def _get_track_uri(self, track): |
196 | uri = track.get_loc_for_io() |
197 | - parsed = urlparse(uri) |
198 | - if parsed[0] == "": |
199 | - uri = "file://" + urllib.pathname2url(uri) |
200 | - uri = uri.encode(common.get_default_encoding()) |
201 | + split = urlparse.urlsplit(uri) |
202 | + assert split[0] != "", _("Exaile now uses absolute URI's, please " |
203 | + "delete/rename your %s directory") \ |
204 | + % xdg.data_home |
205 | + path = common.local_file_from_url(uri) |
206 | + path = urllib.pathname2url(path) |
207 | + uri = urlparse.urlunsplit(split[0:2] + (path, '', '')) |
208 | return uri |
209 | |
210 | def __notify_source(self, *args): |
211 | @@ -478,7 +481,7 @@ |
212 | |
213 | # make sure the file exists if this is supposed to be a local track |
214 | if track.is_local(): |
215 | - if not os.path.exists(track.get_loc()): |
216 | + if not track.exists(): |
217 | logger.error(_("File does not exist: %s") % |
218 | track.get_loc()) |
219 | return False |
220 | @@ -490,7 +493,7 @@ |
221 | self.reset_playtime_stamp() |
222 | |
223 | self.playbin.set_property("uri", uri) |
224 | - if uri.startswith("cdda://"): |
225 | + if urlparse.urlsplit(uri)[0] == "cdda": |
226 | self.notify_id = self.playbin.connect('notify::source', |
227 | self.__notify_source) |
228 | |
229 | |
230 | === modified file 'xl/playlist.py' |
231 | --- xl/playlist.py 2009-04-14 17:34:36 +0000 |
232 | +++ xl/playlist.py 2009-04-14 23:33:28 +0000 |
233 | @@ -40,7 +40,7 @@ |
234 | except ImportError: |
235 | import elementtree as ETree |
236 | |
237 | -from urlparse import urlparse |
238 | +import urlparse |
239 | import logging |
240 | logger = logging.getLogger(__name__) |
241 | |
242 | @@ -209,7 +209,7 @@ |
243 | for track in playlist: |
244 | handle.write("<entry>\n") |
245 | handle.write(" <title>%s</title>\n" % track['title']) |
246 | - handle.write(" <ref href=\"%s\" />\n" % urllib.quote(track.get_loc())) |
247 | + handle.write(" <ref href=\"%s\" />\n" % track.get_loc()) |
248 | handle.write("</entry>\n") |
249 | |
250 | handle.write("</asx>") |
251 | @@ -222,7 +222,7 @@ |
252 | pl = Playlist(name=name) |
253 | for t in tracks: |
254 | tr = track.Track() |
255 | - loc = urllib.unquote(t.find("ref").get("href")) |
256 | + loc = t.find("ref").get("href") |
257 | tr.set_loc(loc) |
258 | tr['title'] = t.find("title").text.strip() |
259 | tr.read_tags() |
260 | @@ -254,11 +254,8 @@ |
261 | if track[tag] == u"": |
262 | continue |
263 | handle.write(" <%s>%s</%s>\n" % (xs, track[tag],xs) ) |
264 | - url = urllib.quote(track.get_loc()) |
265 | - if urlparse(track.get_loc())[0] == "": |
266 | - handle.write(" <location>file://%s</location>\n" % url) |
267 | - else: |
268 | - handle.write(" <location>%s</location>\n" % url) |
269 | + url = track.get_loc() |
270 | + handle.write(" <location>%s</location>\n" % url) |
271 | handle.write(" </track>\n") |
272 | |
273 | handle.write(" </trackList>\n") |
274 | @@ -274,7 +271,7 @@ |
275 | pl = Playlist(name=name) |
276 | for t in tracks: |
277 | tr = track.Track() |
278 | - loc = urllib.unquote(t.find("%slocation"%ns).text.strip()) |
279 | + loc = t.find("%slocation"%ns).text.strip() |
280 | tr.set_loc(loc) |
281 | for xs, tag in XSPF_MAPPING.iteritems(): |
282 | try: |
283 | @@ -441,7 +438,7 @@ |
284 | track: the track to add [Track] |
285 | location: the index to insert at [int] |
286 | """ |
287 | - if os.path.exists(track.get_loc_for_io()) or not ignore_missing_files: |
288 | + if track.exists() or not ignore_missing_files: |
289 | self.add_tracks([track], location) |
290 | |
291 | def add_tracks(self, tracks, location=None, add_duplicates=True): |
292 | |
293 | === modified file 'xl/track.py' |
294 | --- xl/track.py 2009-03-24 23:16:10 +0000 |
295 | +++ xl/track.py 2009-04-18 06:01:50 +0000 |
296 | @@ -20,6 +20,9 @@ |
297 | import xl.metadata as metadata |
298 | from xl.common import lstrip_special |
299 | import logging, traceback |
300 | +import urlparse |
301 | +import urllib |
302 | +import urllib2 |
303 | logger = logging.getLogger(__name__) |
304 | |
305 | settings = settings.SettingsManager.settings |
306 | @@ -61,8 +64,10 @@ |
307 | |
308 | loc: the location [string] |
309 | """ |
310 | - if loc.startswith("file://"): |
311 | - loc = loc[7:] |
312 | + split = urlparse.urlsplit(loc) |
313 | + if split[0] == "": |
314 | + loc = os.path.abspath(loc) |
315 | + loc = urlparse.urlunsplit(('file', split[1], loc, '', '')) |
316 | self['loc'] = loc |
317 | |
318 | def get_loc(self): |
319 | @@ -77,6 +82,22 @@ |
320 | except: |
321 | return self['loc'] |
322 | |
323 | + def exists(self): |
324 | + if self.is_local(): |
325 | + return os.path.exists(self.local_file_name()) |
326 | + else: |
327 | + try: |
328 | + urllib2.urlopen(self.get_loc_for_io()) |
329 | + except urllib2.URLError, urllib2.HTTPError: |
330 | + return False |
331 | + else: |
332 | + return True |
333 | + |
334 | + def local_file_name(self): |
335 | + if not self.is_local(): |
336 | + return None |
337 | + return common.local_file_from_url(self.get_loc_for_io()) |
338 | + |
339 | def get_loc_for_io(self): |
340 | """ |
341 | Gets the location in its original form. should always be correct. |
342 | @@ -207,9 +228,11 @@ |
343 | |
344 | |
345 | # fill out file specific items |
346 | - mtime = os.path.getmtime(self.get_loc_for_io()) |
347 | + split = urlparse.urlsplit(self.get_loc_for_io()) |
348 | + path = self.local_file_name() |
349 | + mtime = os.path.getmtime(path) |
350 | self['modified'] = mtime |
351 | - self['basedir'] = os.path.dirname(self.get_loc_for_io()) |
352 | + self['basedir'] = os.path.dirname(path) |
353 | self._dirty = True |
354 | return f |
355 | except: |
356 | @@ -217,7 +240,7 @@ |
357 | return False |
358 | |
359 | def is_local(self): |
360 | - return urlparse(self.get_loc())[0] == "" |
361 | + return urlparse.urlsplit(self.get_loc()).scheme == "file" |
362 | |
363 | def get_track(self): |
364 | """ |
Forces exaile to only keep full absolute URI's internally.
Because of the unicode issue, tracks store a "file:///path" in unicode with no escaped characters, rather than a properly urlencoded one. This is so that we can look up the unicode os path again later. The player has to deal with any issues that come out of that when passing to gstreamer. All paths also become absolute rather than relative since absolute uri's are by definition absolute.
This branch will cause all users to have to delete their database and, more likely, nuke their ~/.local/ share/exaile folder. This was discussed as acceptable on IRC since we are still in Alpha