Skip to content

Commit

Permalink
Added loop to iterate over sanitize/truncate until stable. Enabled te…
Browse files Browse the repository at this point in the history
…st_truncation_does_not_conflict_with_replacement test. Fixes #496.
  • Loading branch information
LordSputnik committed May 10, 2015
1 parent f497bf8 commit 4ef44f6
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 21 deletions.
86 changes: 66 additions & 20 deletions beets/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,71 @@ def move(self, copy=False, link=False, basedir=None, with_album=True):

# Templating.

def _legalize_partial(self, path, fragment, replacements):
""" Perform a partial legalization of the path (ie. a single
sanitization and truncation). Outputs unicode if fragment is set,
otherwise bytes.
"""

# Truncate components and remove forbidden characters.
path = util.sanitize_path(path, replacements)

# Encode for the filesystem.
if not fragment:
path = bytestring_path(path)

# Preserve extension.
_, extension = os.path.splitext(self.path)
if fragment:
# Outputting Unicode.
extension = extension.decode('utf8', 'ignore')
path += extension.lower()

# Truncate too-long components.
maxlen = beets.config['max_filename_length'].get(int)
if not maxlen:
# When zero, try to determine from filesystem.
maxlen = util.max_filename_length(self._db.directory)
path = util.truncate_path(path, maxlen)

return path

def _legalize_path(self, path, fragment):
""" Perform several iterations of _legalize_partial, to generate a
stable, optimal output path. This is necessary for cases where
truncation produces unclean paths (eg. trailing space).
"""

# Create a list of path candidates
path_candidates = [b'']

replacements = self._db.replacements

# Perform an initial pass
path = self._legalize_partial(path, fragment, replacements)
while path != path_candidates[-1]:
# This will keep sanitizing the path until it's stable, or an
# infinite loop appears
while path not in path_candidates:
path_candidates.append(path)
# Convert back to Unicode with extension removed
print(util.displayable_path(path))
path = os.path.splitext(util.displayable_path(path))[0]

# Run next pass
path = self._legalize_partial(path, fragment, replacements)

# If an infinite loop occurred, adjust replacements to avoid it
if path != path_candidates[-1]:
replacements = dict((k, u'_') for k, v in replacements)

# If there's a rule to match a single underscore, set the
# target to a blank string.
if '_' in replacements:
replacements['_'] = ''

return path

def destination(self, fragment=False, basedir=None, platform=None,
path_formats=None):
"""Returns the path in the library directory designated for the
Expand Down Expand Up @@ -781,26 +846,7 @@ def destination(self, fragment=False, basedir=None, platform=None,
if beets.config['asciify_paths']:
subpath = unidecode(subpath)

# Truncate components and remove forbidden characters.
subpath = util.sanitize_path(subpath, self._db.replacements)

# Encode for the filesystem.
if not fragment:
subpath = bytestring_path(subpath)

# Preserve extension.
_, extension = os.path.splitext(self.path)
if fragment:
# Outputting Unicode.
extension = extension.decode('utf8', 'ignore')
subpath += extension.lower()

# Truncate too-long components.
maxlen = beets.config['max_filename_length'].get(int)
if not maxlen:
# When zero, try to determine from filesystem.
maxlen = util.max_filename_length(self._db.directory)
subpath = util.truncate_path(subpath, maxlen)
subpath = self._legalize_path(subpath, fragment)

if fragment:
return subpath
Expand Down
1 change: 0 additions & 1 deletion test/test_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,6 @@ def test_destination_with_empty_final_component(self):
self.assertEqual(self.i.destination(),
np('base/one/_.mp3'))

@unittest.skip('unimplemented: #496')
def test_truncation_does_not_conflict_with_replacement(self):
# Use a replacement that should always replace the last X in any
# path component with a Z.
Expand Down

0 comments on commit 4ef44f6

Please sign in to comment.