Example #1
0
    def scan(self, paths, exclude=[], cofuncid=None):
        added = []
        exclude = [expanduser(path) for path in exclude if path]

        def need_yield(last_yield=[0]):
            current = time.time()
            if abs(current - last_yield[0]) > 0.015:
                last_yield[0] = current
                return True
            return False

        def need_added(last_added=[0]):
            current = time.time()
            if abs(current - last_added[0]) > 1.0:
                last_added[0] = current
                return True
            return False

        for fullpath in paths:
            print_d("Scanning %r." % fullpath, self)
            desc = _("Scanning %s") % (unexpand(fsdecode(fullpath)))
            with Task(_("Library"), desc) as task:
                if cofuncid:
                    task.copool(cofuncid)
                fullpath = expanduser(fullpath)
                if filter(fullpath.startswith, exclude):
                    continue
                for path, dnames, fnames in os.walk(fullpath):
                    for filename in fnames:
                        fullfilename = os.path.join(path, filename)
                        if filter(fullfilename.startswith, exclude):
                            continue
                        if fullfilename not in self._contents:
                            fullfilename = os.path.realpath(fullfilename)
                            # skip unknown file extensions
                            if not formats.filter(fullfilename):
                                continue
                            if filter(fullfilename.startswith, exclude):
                                continue
                            if fullfilename not in self._contents:
                                item = self.add_filename(fullfilename, False)
                                if item is not None:
                                    added.append(item)
                                    if len(added) > 100 or need_added():
                                        self.add(added)
                                        added = []
                                        task.pulse()
                                        yield
                                if added and need_yield():
                                    yield
                if added:
                    self.add(added)
                    added = []
                    task.pulse()
                    yield True
Example #2
0
    def scan(self, paths, exclude=[], cofuncid=None):
        added = []
        exclude = [expanduser(path) for path in exclude if path]

        def need_yield(last_yield=[0]):
            current = time.time()
            if abs(current - last_yield[0]) > 0.015:
                last_yield[0] = current
                return True
            return False

        def need_added(last_added=[0]):
            current = time.time()
            if abs(current - last_added[0]) > 1.0:
                last_added[0] = current
                return True
            return False

        for fullpath in paths:
            print_d("Scanning %r." % fullpath, self)
            desc = _("Scanning %s") % (unexpand(fsdecode(fullpath)))
            with Task(_("Library"), desc) as task:
                if cofuncid:
                    task.copool(cofuncid)
                fullpath = expanduser(fullpath)
                if filter(fullpath.startswith, exclude):
                    continue
                for path, dnames, fnames in os.walk(fullpath):
                    for filename in fnames:
                        fullfilename = os.path.join(path, filename)
                        if filter(fullfilename.startswith, exclude):
                            continue
                        if fullfilename not in self._contents:
                            fullfilename = os.path.realpath(fullfilename)
                            # skip unknown file extensions
                            if not formats.filter(fullfilename):
                                continue
                            if filter(fullfilename.startswith, exclude):
                                continue
                            if fullfilename not in self._contents:
                                item = self.add_filename(fullfilename, False)
                                if item is not None:
                                    added.append(item)
                                    if len(added) > 100 or need_added():
                                        self.add(added)
                                        added = []
                                        task.pulse()
                                        yield
                                if added and need_yield():
                                    yield
                if added:
                    self.add(added)
                    added = []
                    task.pulse()
                    yield True
Example #3
0
def do_import(parent, library):
    db_path = expanduser(BansheeImport.USR_PATH)

    importer = BansheeDBImporter(library)
    try:
        db = sqlite3.connect(db_path)
        importer.read(db)
        db.close()
    except sqlite3.OperationalError:
        msg = _("Specified Banshee database is malformed or missing")
        WarningMessage(parent, BansheeImport.PLUGIN_NAME, msg).run()
    except Exception:
        util.print_exc()
        importer.finish()
        msg = _("Import Failed")
        # FIXME: don't depend on the plugin class here
        ErrorMessage(parent, BansheeImport.PLUGIN_NAME, msg).run()
    else:
        count = importer.finish()
        msg = ngettext(
            "Successfully imported ratings and statistics for %d song",
            "Successfully imported ratings and statistics for %d songs",
            count) % count
        Message(Gtk.MessageType.INFO, parent, BansheeImport.PLUGIN_NAME,
                msg).run()
Example #4
0
    def _post(self, value, song, keep_extension=True):
        if value:
            assert isinstance(value, unicode)
            value = fsnative(value)

            if keep_extension:
                fn = song.get("~filename", ".")
                ext = fn[fn.rfind("."):].lower()
                val_ext = value[-len(ext):].lower()
                if not ext == val_ext:
                    value += ext.lower()

            if os.name == "nt":
                assert isinstance(value, unicode)
                value = strip_win32_incompat_from_path(value)

            value = expanduser(value)

            # Limit each path section to 255 (bytes on linux, chars on win).
            # http://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits
            path, ext = os.path.splitext(value)
            path = path.split(sep)
            limit = [255] * len(path)
            limit[-1] -= len(ext)
            elip = lambda (p, l): (len(p) > l and p[:l - 2] + "..") or p
            path = sep.join(map(elip, zip(path, limit)))
            value = path + ext

            if sep in value and not os.path.isabs(value):
                raise ValueError("Pattern is not rooted")
        return value
Example #5
0
class Tunexpand(TestCase):
    d = expanduser("~")
    u = unexpand(d)

    def test_base(self):
        path = unexpand(self.d)
        if is_win:
            self.failUnlessEqual(path, "%USERPROFILE%")
        else:
            self.failUnlessEqual(path, "~")

    def test_only_profile_case(self):
        assert isinstance(unexpand(expanduser(fsnative(u"~"))), fsnative)

    def test_base_trailing(self):
        path = unexpand(self.d + os.path.sep)
        self.failUnlessEqual(path, self.u + os.path.sep)

    def test_noprefix(self):
        path = unexpand(self.d + "foobar" + os.path.sep)
        self.failUnlessEqual(path, self.d + "foobar" + os.path.sep)

    def test_subfile(self):
        path = unexpand(os.path.join(self.d, "la", "la"))
        self.failUnlessEqual(path, os.path.join(self.u, "la", "la"))
Example #6
0
    def _post(self, value, song, keep_extension=True):
        if value:
            assert isinstance(value, unicode)
            value = fsnative(value)

            if keep_extension:
                fn = song.get("~filename", ".")
                ext = fn[fn.rfind("."):].lower()
                val_ext = value[-len(ext):].lower()
                if not ext == val_ext:
                    value += ext.lower()

            if os.name == "nt":
                assert isinstance(value, unicode)
                value = strip_win32_incompat_from_path(value)

            value = expanduser(value)

            # Limit each path section to 255 (bytes on linux, chars on win).
            # http://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits
            path, ext = os.path.splitext(value)
            path = path.split(sep)
            limit = [255] * len(path)
            limit[-1] -= len(ext)
            elip = lambda (p, l): (len(p) > l and p[:l - 2] + "..") or p
            path = sep.join(map(elip, zip(path, limit)))
            value = path + ext

            if sep in value and not os.path.isabs(value):
                raise ValueError("Pattern is not rooted")
        return value
Example #7
0
 def lyric_filename(self):
     """Returns the (potential) lyrics filename for this file"""
     # TODO: Use better filesystem sanitisation for lyrics file path.
     filename = self.comma("title").replace('/', '')[:128] + '.lyric'
     sub_dir = ((self.comma("lyricist") or self.comma("artist"))
               .replace('/', '')[:128])
     path = os.path.join(expanduser("~/.lyrics"), sub_dir, filename)
     return fsencode(path)
Example #8
0
 def scan(self, paths, exclude=[], cofuncid=None):
     added = []
     exclude = [expanduser(path) for path in exclude if path]
     for fullpath in paths:
         print_d("Scanning %r." % fullpath, self)
         desc = _("Scanning %s") % (unexpand(fsdecode(fullpath)))
         with Task(_("Library"), desc) as task:
             if cofuncid:
                 task.copool(cofuncid)
             fullpath = expanduser(fullpath)
             if filter(fullpath.startswith, exclude):
                 continue
             for path, dnames, fnames in os.walk(util.fsnative(fullpath)):
                 for filename in fnames:
                     fullfilename = os.path.join(path, filename)
                     if filter(fullfilename.startswith, exclude):
                         continue
                     if fullfilename not in self._contents:
                         fullfilename = os.path.realpath(fullfilename)
                         # skip unknown file extensions
                         if not formats.filter(fullfilename):
                             continue
                         if filter(fullfilename.startswith, exclude):
                             continue
                         if fullfilename not in self._contents:
                             item = self.add_filename(fullfilename, False)
                             if item is not None:
                                 added.append(item)
                                 if len(added) > 20:
                                     self.add(added)
                                     added = []
                                     task.pulse()
                                     yield True
                 if added:
                     self.add(added)
                     added = []
                     task.pulse()
                     yield True
Example #9
0
 def expand_pathfile(rpf):
     """Return the expanded RootPathFile"""
     expanded = []
     root = expanduser(rpf.root)
     pathfile = expanduser(rpf.pathfile)
     if rx_params.search(pathfile):
         root = expand_patterns(root).format(self)
         pathfile = expand_patterns(pathfile).format(self)
     rpf = RootPathFile(root, pathfile)
     expanded.append(rpf)
     if not os.path.exists(pathfile) and is_windows():
         # prioritise a special character encoded version
         #
         # most 'alien' chars are supported for 'nix fs paths, and we
         # only pass the proposed path through 'escape_filename' (which
         # apparently doesn't respect case) if we don't care about case!
         #
         # FIX: assumes 'nix build used on a case-sensitive fs, nt case
         # insensitive. clearly this is not biting anyone though (yet!)
         pathfile = os.path.sep.join([rpf.root, rpf.end_escaped])
         rpf = RootPathFile(rpf.root, pathfile)
         expanded.insert(len(expanded) - 1, rpf)
     return expanded
Example #10
0
 def expand_pathfile(rpf):
     """Return the expanded RootPathFile"""
     expanded = []
     root = expanduser(rpf.root)
     pathfile = expanduser(rpf.pathfile)
     if rx_params.search(pathfile):
         root = expand_patterns(root).format(self)
         pathfile = expand_patterns(pathfile).format(self)
     rpf = RootPathFile(root, pathfile)
     expanded.append(rpf)
     if not os.path.exists(pathfile) and is_windows():
         # prioritise a special character encoded version
         #
         # most 'alien' chars are supported for 'nix fs paths, and we
         # only pass the proposed path through 'escape_filename' (which
         # apparently doesn't respect case) if we don't care about case!
         #
         # FIX: assumes 'nix build used on a case-sensitive fs, nt case
         # insensitive. clearly this is not biting anyone though (yet!)
         pathfile = os.path.sep.join([rpf.root, rpf.end_escaped])
         rpf = RootPathFile(rpf.root, pathfile)
         expanded.insert(len(expanded) - 1, rpf)
     return expanded
Example #11
0
def do_import(parent, library):
    db_path = expanduser("~/.local/share/rhythmbox/rhythmdb.xml")
    handler = RBDBContentHandler(library)
    try:
        xml.sax.parse(db_path, handler)
    except Exception:
        util.print_exc()
        handler.finish()
        msg = _("Import Failed")
        # FIXME: don't depend on the plugin class here..
        ErrorMessage(parent, RBImport.PLUGIN_NAME, msg).run()
    else:
        count = handler.finish()
        msg = _("Successfully imported ratings and statistics "
                "for %d songs") % count
        # FIXME: this is just a warning so it works with older QL
        WarningMessage(parent, RBImport.PLUGIN_NAME, msg).run()
Example #12
0
    def lyric_filename(self):
        """Returns the (potential) lyrics filename for this file"""

        filename = self.comma("title").replace(u"/", u"")[:128] + u".lyric"
        sub_dir = (self.comma("lyricist") or self.comma("artist")).replace(u"/", u"")[:128]

        if os.name == "nt":
            # this was added at a later point. only use escape_filename here
            # to keep the linux case the same as before
            filename = escape_filename(filename)
            sub_dir = escape_filename(sub_dir)
        else:
            filename = fsnative(filename)
            sub_dir = fsnative(sub_dir)

        path = os.path.join(expanduser(fsnative(u"~/.lyrics")), sub_dir, filename)
        return path
Example #13
0
def do_import(parent, library):
    db_path = expanduser("~/.local/share/rhythmbox/rhythmdb.xml")
    handler = RBDBContentHandler(library)
    try:
        xml.sax.parse(db_path, handler)
    except Exception:
        util.print_exc()
        handler.finish()
        msg = _("Import Failed")
        # FIXME: don't depend on the plugin class here..
        ErrorMessage(parent, RBImport.PLUGIN_NAME, msg).run()
    else:
        count = handler.finish()
        msg = _("Successfully imported ratings and statistics "
                "for %d songs") % count
        # FIXME: this is just a warning so it works with older QL
        WarningMessage(parent, RBImport.PLUGIN_NAME, msg).run()
Example #14
0
def do_import(parent, library):
    plist_path = expanduser("~/Music/iTunes/iTunes Music Library.xml")
    importer = iTunesimporter(library)
    try:
        plist = plistlib.readPlist(plist_path)
        importer.read(plist)
    except Exception:
        util.print_exc()
        importer.finish()
        msg = _("Import Failed")
        # FIXME: don't depend on the plugin class here..
        ErrorMessage(parent, iTunesImport.PLUGIN_NAME, msg).run()
    else:
        count = importer.finish()
        msg = _("Successfully imported ratings and statistics "
                "for %d songs") % count
        # FIXME: this is just a warning so it works with older QL
        WarningMessage(parent, iTunesimport.PLUGIN_NAME, msg).run()
Example #15
0
    def lyric_filename(self):
        """Returns the (potential) lyrics filename for this file"""

        filename = self.comma("title").replace(u'/', u'')[:128] + u'.lyric'
        sub_dir = ((self.comma("lyricist")
                    or self.comma("artist")).replace(u'/', u'')[:128])

        if os.name == "nt":
            # this was added at a later point. only use escape_filename here
            # to keep the linux case the same as before
            filename = escape_filename(filename)
            sub_dir = escape_filename(sub_dir)
        else:
            filename = fsnative(filename)
            sub_dir = fsnative(sub_dir)

        path = os.path.join(expanduser(fsnative(u"~/.lyrics")), sub_dir,
                            filename)
        return path
Example #16
0
    def _post(self, value, song, keep_extension=True):
        if value:
            assert isinstance(value, unicode)
            value = fsnative(value)

            if keep_extension:
                fn = song.get("~filename", ".")
                ext = fn[fn.rfind(".") :].lower()
                val_ext = value[-len(ext) :].lower()
                if not ext == val_ext:
                    value += ext.lower()

            if os.name == "nt":
                assert isinstance(value, unicode)
                value = strip_win32_incompat_from_path(value)

            value = expanduser(value)
            value = limit_path(value)

            if sep in value and not os.path.isabs(value):
                raise ValueError("Pattern is not rooted")
        return value
Example #17
0
    def _post(self, value, song, keep_extension=True):
        if value:
            assert isinstance(value, unicode)
            value = fsnative(value)

            if keep_extension:
                fn = song.get("~filename", ".")
                ext = fn[fn.rfind("."):].lower()
                val_ext = value[-len(ext):].lower()
                if not ext == val_ext:
                    value += ext.lower()

            if os.name == "nt":
                assert isinstance(value, unicode)
                value = strip_win32_incompat_from_path(value)

            value = expanduser(value)
            value = limit_path(value)

            if sep in value and not os.path.isabs(value):
                raise ValueError("Pattern is not rooted")
        return value
Example #18
0
 def test_only_profile_case(self):
     assert isinstance(unexpand(expanduser(fsnative(u"~"))), fsnative)
Example #19
0
 def test_only_profile_case(self):
     assert isinstance(unexpand(expanduser(fsnative(u"~"))), fsnative)
Example #20
0
def query(category, discid, xcode='utf8:utf8'):
    discinfo = {}
    tracktitles = {}
    dump = path.join(expanduser("~"), '.cddb', category, discid)
    try:
        for line in file(dump):
            if line.startswith("TTITLE"):
                track, title = line.split("=", 1)
                try:
                    track = int(track[6:])
                except (ValueError):
                    pass
                else:
                    tracktitles[track] = \
                        title.decode('utf-8', 'replace').strip()
            elif line.startswith("DGENRE"):
                discinfo['genre'] = line.split('=', 1)[1].strip()
            elif line.startswith("DTITLE"):
                dtitle = line.split('=', 1)[1].strip().split(' / ', 1)
                if len(dtitle) == 2:
                    discinfo['artist'], discinfo['title'] = dtitle
                else:
                    discinfo['title'] = dtitle[0].strip()
            elif line.startswith("DYEAR"):
                discinfo['year'] = line.split('=', 1)[1].strip()
    except EnvironmentError:
        pass
    else:
        return discinfo, tracktitles

    read, info = CDDB.read(category, discid, **CLIENTINFO)
    if read != 210:
        return None

    try:
        os.makedirs(path.join(expanduser("~"), '.cddb'))
    except EnvironmentError:
        pass
    try:
        save = file(dump, 'w')
        keys = info.keys()
        keys.sort()
        for key in keys:
            print>>save, "%s=%s" % (key, info[key])
        save.close()
    except EnvironmentError:
        pass

    xf, xt = xcode.split(':')
    for key, value in info.iteritems():
        try:
            value = value.decode('utf-8', 'replace').strip().encode(
                xf, 'replace').decode(xt, 'replace')
        except AttributeError:
            pass
        if key.startswith('TTITLE'):
            try:
                tracktitles[int(key[6:])] = value
            except ValueError:
                pass
        elif key == 'DGENRE':
            discinfo['genre'] = value
        elif key == 'DTITLE':
            dtitle = value.strip().split(' / ', 1)
            if len(dtitle) == 2:
                discinfo['artist'], discinfo['title'] = dtitle
            else:
                discinfo['title'] = dtitle[0].strip()
        elif key == 'DYEAR':
            discinfo['year'] = value

    return discinfo, tracktitles