Example #1
0
 def test_component_sanitize_uses_khz_samplerate(self):
     val = util.sanitize_for_path(12345, posixpath, 'samplerate')
     self.assertEqual(val, u'12kHz')
Example #2
0
 def test_component_sanitize_pads_with_zero(self):
     name = util.sanitize_for_path(1, posixpath, 'track')
     self.assertTrue(name.startswith('0'))
Example #3
0
 def test_component_sanitize_uses_kbps_bitrate(self):
     val = util.sanitize_for_path(12345, posixpath, 'bitrate')
     self.assertEqual(val, u'12kbps')
Example #4
0
 def destination(self, item, pathmod=None, in_album=False,
                 fragment=False, basedir=None):
     """Returns the path in the library directory designated for item
     item (i.e., where the file ought to be). in_album forces the
     item to be treated as part of an album. fragment makes this
     method return just the path fragment underneath the root library
     directory; the path is also returned as Unicode instead of
     encoded as a bytestring. basedir can override the library's base
     directory for the destination.
     """
     pathmod = pathmod or os.path
     
     # Use a path format based on the album type, if available.
     if not item.album_id and not in_album:
         # Singleton track. Never use the "album" formats.
         if 'singleton' in self.path_formats:
             path_format = self.path_formats['singleton']
         else:
             path_format = self.path_formats['default']
     elif item.albumtype and item.albumtype in self.path_formats:
         path_format = self.path_formats[item.albumtype]
     elif item.comp and 'comp' in self.path_formats:
         path_format = self.path_formats['comp']
     else:
         path_format = self.path_formats['default']
     subpath_tmpl = Template(path_format)
     
     # Get the item's Album if it has one.
     album = self.get_album(item)
     
     # Build the mapping for substitution in the path template,
     # beginning with the values from the database.
     mapping = {}
     for key in ITEM_KEYS_META:
         # Get the values from either the item or its album.
         if key in ALBUM_KEYS_ITEM and album is not None:
             # From album.
             value = getattr(album, key)
         else:
             # From Item.
             value = getattr(item, key)
         mapping[key] = util.sanitize_for_path(value, pathmod, key)
     
     # Use the album artist if the track artist is not set and
     # vice-versa.
     if not mapping['artist']:
         mapping['artist'] = mapping['albumartist']
     if not mapping['albumartist']:
         mapping['albumartist'] = mapping['artist']
     
     # Perform substitution.
     subpath = subpath_tmpl.substitute(mapping)
     
     # Encode for the filesystem, dropping unencodable characters.
     if isinstance(subpath, unicode) and not fragment:
         encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
         subpath = subpath.encode(encoding, 'replace')
     
     # Truncate components and remove forbidden characters.
     subpath = util.sanitize_path(subpath)
     
     # Preserve extension.
     _, extension = pathmod.splitext(item.path)
     subpath += extension
     
     if fragment:
         return subpath
     else:
         basedir = basedir or self.directory
         return normpath(os.path.join(basedir, subpath))   
Example #5
0
 def test_component_sanitize_replaces_separators(self):
     name = posixpath.join('a', 'b')
     newname = util.sanitize_for_path(name, posixpath)
     self.assertNotEqual(name, newname)
Example #6
0
 def test_component_sanitize_uses_kbps_bitrate(self):
     val = util.sanitize_for_path(12345, posixpath, 'bitrate')
     self.assertEqual(val, u'12kbps')
Example #7
0
 def test_component_sanitize_uses_khz_samplerate(self):
     val = util.sanitize_for_path(12345, posixpath, 'samplerate')
     self.assertEqual(val, u'12kHz')
Example #8
0
 def test_component_sanitize_pads_with_zero(self):
     name = util.sanitize_for_path(1, posixpath, 'track')
     self.assertTrue(name.startswith('0'))
Example #9
0
 def test_component_sanitize_replaces_separators(self):
     name = posixpath.join('a', 'b')
     newname = util.sanitize_for_path(name, posixpath)
     self.assertNotEqual(name, newname)
Example #10
0
 def destination(self, item, pathmod=None, in_album=False,
                 fragment=False, basedir=None):
     """Returns the path in the library directory designated for item
     item (i.e., where the file ought to be). in_album forces the
     item to be treated as part of an album. fragment makes this
     method return just the path fragment underneath the root library
     directory; the path is also returned as Unicode instead of
     encoded as a bytestring. basedir can override the library's base
     directory for the destination.
     """
     pathmod = pathmod or os.path
     
     # Use a path format based on a query, falling back on the
     # default.
     for query, path_format in self.path_formats:
         if query == PF_KEY_DEFAULT:
             continue
         query = AndQuery.from_string(query)
         if in_album:
             # If we're treating this item as a member of the item,
             # hack the query so that singleton queries always
             # observe the item to be non-singleton.
             for i, subquery in enumerate(query):
                 if isinstance(subquery, SingletonQuery):
                     query[i] = FalseQuery() if subquery.sense \
                                else TrueQuery()
         if query.match(item):
             # The query matches the item! Use the corresponding path
             # format.
             break
     else:
         # No query matched; fall back to default.
         for query, path_format in self.path_formats:
             if query == PF_KEY_DEFAULT:
                 break
         else:
             assert False, "no default path format"
     subpath_tmpl = Template(path_format)
     
     # Get the item's Album if it has one.
     album = self.get_album(item)
     
     # Build the mapping for substitution in the path template,
     # beginning with the values from the database.
     mapping = {}
     for key in ITEM_KEYS_META:
         # Get the values from either the item or its album.
         if key in ALBUM_KEYS_ITEM and album is not None:
             # From album.
             value = getattr(album, key)
         else:
             # From Item.
             value = getattr(item, key)
         mapping[key] = util.sanitize_for_path(value, pathmod, key)
     
     # Use the album artist if the track artist is not set and
     # vice-versa.
     if not mapping['artist']:
         mapping['artist'] = mapping['albumartist']
     if not mapping['albumartist']:
         mapping['albumartist'] = mapping['artist']
     
     # Perform substitution.
     mapping.update(plugins.template_values(item))
     funcs = dict(TEMPLATE_FUNCTIONS)
     funcs.update(plugins.template_funcs())
     subpath = subpath_tmpl.substitute(mapping, funcs)
     
     # Encode for the filesystem, dropping unencodable characters.
     if isinstance(subpath, unicode) and not fragment:
         encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
         subpath = subpath.encode(encoding, 'replace')
     
     # Truncate components and remove forbidden characters.
     subpath = util.sanitize_path(subpath, pathmod, self.replacements)
     
     # Preserve extension.
     _, extension = pathmod.splitext(item.path)
     subpath += extension
     
     if fragment:
         return subpath
     else:
         basedir = basedir or self.directory
         return normpath(os.path.join(basedir, subpath))   
Example #11
0
 def destination(self, item, pathmod=None, in_album=False,
                 fragment=False, basedir=None):
     """Returns the path in the library directory designated for item
     item (i.e., where the file ought to be). in_album forces the
     item to be treated as part of an album. fragment makes this
     method return just the path fragment underneath the root library
     directory; the path is also returned as Unicode instead of
     encoded as a bytestring. basedir can override the library's base
     directory for the destination.
     """
     pathmod = pathmod or os.path
     
     # Use a path format based on a query, falling back on the
     # default.
     for query, path_format in self.path_formats:
         if query == PF_KEY_DEFAULT:
             continue
         query = AndQuery.from_string(query)
         if in_album:
             # If we're treating this item as a member of the item,
             # hack the query so that singleton queries always
             # observe the item to be non-singleton.
             for i, subquery in enumerate(query):
                 if isinstance(subquery, SingletonQuery):
                     query[i] = FalseQuery() if subquery.sense \
                                else TrueQuery()
         if query.match(item):
             # The query matches the item! Use the corresponding path
             # format.
             break
     else:
         # No query matched; fall back to default.
         for query, path_format in self.path_formats:
             if query == PF_KEY_DEFAULT:
                 break
         else:
             assert False, "no default path format"
     subpath_tmpl = Template(path_format)
     
     # Get the item's Album if it has one.
     album = self.get_album(item)
     
     # Build the mapping for substitution in the path template,
     # beginning with the values from the database.
     mapping = {}
     for key in ITEM_KEYS_META:
         # Get the values from either the item or its album.
         if key in ALBUM_KEYS_ITEM and album is not None:
             # From album.
             value = getattr(album, key)
         else:
             # From Item.
             value = getattr(item, key)
         mapping[key] = util.sanitize_for_path(value, pathmod, key)
     
     # Use the album artist if the track artist is not set and
     # vice-versa.
     if not mapping['artist']:
         mapping['artist'] = mapping['albumartist']
     if not mapping['albumartist']:
         mapping['albumartist'] = mapping['artist']
     
     # Perform substitution.
     mapping.update(plugins.template_values(item))
     funcs = dict(TEMPLATE_FUNCTIONS)
     funcs.update(plugins.template_funcs())
     subpath = subpath_tmpl.substitute(mapping, funcs)
     
     # Encode for the filesystem, dropping unencodable characters.
     if isinstance(subpath, unicode) and not fragment:
         encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
         subpath = subpath.encode(encoding, 'replace')
     
     # Truncate components and remove forbidden characters.
     subpath = util.sanitize_path(subpath, pathmod, self.replacements)
     
     # Preserve extension.
     _, extension = pathmod.splitext(item.path)
     subpath += extension
     
     if fragment:
         return subpath
     else:
         basedir = basedir or self.directory
         return normpath(os.path.join(basedir, subpath))   
Example #12
0
    def destination(self, item, pathmod=None, in_album=False):
        """Returns the path in the library directory designated for item
        item (i.e., where the file ought to be). in_album forces the
        item to be treated as part of an album.
        """
        pathmod = pathmod or os.path

        # Use a path format based on the album type, if available.
        if not item.album_id and not in_album:
            # Singleton track. Never use the "album" formats.
            if 'singleton' in self.path_formats:
                path_format = self.path_formats['singleton']
            else:
                path_format = self.path_formats['default']
        elif item.albumtype and item.albumtype in self.path_formats:
            path_format = self.path_formats[item.albumtype]
        elif item.comp and 'comp' in self.path_formats:
            path_format = self.path_formats['comp']
        else:
            path_format = self.path_formats['default']
        subpath_tmpl = Template(path_format)

        # Get the item's Album if it has one.
        album = self.get_album(item)

        # Build the mapping for substitution in the path template,
        # beginning with the values from the database.
        mapping = {}
        for key in ITEM_KEYS_META:
            # Get the values from either the item or its album.
            if key in ALBUM_KEYS_ITEM and album is not None:
                # From album.
                value = getattr(album, key)
            else:
                # From Item.
                value = getattr(item, key)
            mapping[key] = util.sanitize_for_path(value, pathmod, key)

        # Use the album artist if the track artist is not set and
        # vice-versa.
        if not mapping['artist']:
            mapping['artist'] = mapping['albumartist']
        if not mapping['albumartist']:
            mapping['albumartist'] = mapping['artist']

        # Perform substitution.
        subpath = subpath_tmpl.substitute(mapping)

        # Encode for the filesystem, dropping unencodable characters.
        if isinstance(subpath, unicode):
            encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
            subpath = subpath.encode(encoding, 'replace')

        # Truncate components and remove forbidden characters.
        subpath = util.sanitize_path(subpath)

        # Preserve extension.
        _, extension = pathmod.splitext(item.path)
        subpath += extension

        return normpath(os.path.join(self.directory, subpath))