Skip to content

Commit

Permalink
new: Check for version incompatibilities during setter, and slight re…
Browse files Browse the repository at this point in the history
…factor.
  • Loading branch information
nicfit committed Nov 4, 2017
1 parent d635846 commit d7f1711
Showing 1 changed file with 33 additions and 11 deletions.
44 changes: 33 additions & 11 deletions src/eyed3/id3/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@ def version(self):

@version.setter
def version(self, v):
# Tag version changes required possible frame conversion
std, non = self._checkForConversions(v)
converted = []
if non:
converted = self._convertFrames(std, non, v)
if converted:
self.frame_set.clear()
for frame in (std + converted):
self.frame_set[frame.id] = frame

self.header.version = v

def isV1(self):
Expand Down Expand Up @@ -871,13 +881,20 @@ def encode(s):
tag_file.write(tag)
tag_file.flush()

def _render(self, version, curr_tag_size, max_padding_size):
def _checkForConversions(self, target_version):
"""Check the current frame set against `target_version` for frames
requiring conversion.
:param: The version the frames need to map to.
:returns: A 2-tuple where the first element is a list of frames that
are accepted for `target_version`, and the second a list of frames
requiring conversion.
"""
std_frames = []
non_std_frames = []
for f in self.frame_set.getAllFrames():
try:
_, fversion, _ = frames.ID3_FRAMES[f.id]
if fversion in (version, ID3_V2):
if fversion in (target_version, ID3_V2):
std_frames.append(f)
else:
non_std_frames.append(f)
Expand All @@ -886,7 +903,7 @@ def _render(self, version, curr_tag_size, max_padding_size):
try:
_, fversion, _ = frames.NONSTANDARD_ID3_FRAMES[f.id]
# but is it one we can handle.
if fversion in (version, ID3_V2):
if fversion in (target_version, ID3_V2):
std_frames.append(f)
else:
non_std_frames.append(f)
Expand All @@ -895,14 +912,18 @@ def _render(self, version, curr_tag_size, max_padding_size):
# check there.
non_std_frames.append(f)

return std_frames, non_std_frames

def _render(self, version, curr_tag_size, max_padding_size):
converted_frames = []
std_frames , non_std_frames = self._checkForConversions(version)
if non_std_frames:
# actually, they're not converted yet
non_std_frames = self._convertFrames(std_frames, non_std_frames,
version)
converted_frames = self._convertFrames(std_frames, non_std_frames,
version)

# Render all frames first so the data size is known for the tag header.
frame_data = b""
for f in std_frames + non_std_frames:
for f in std_frames + converted_frames:
frame_header = frames.FrameHeader(f.id, version)
if f.header:
frame_header.copyFlags(f.header)
Expand Down Expand Up @@ -1032,7 +1053,7 @@ def _saveV2Tag(self, version, encoding, max_padding):
self.file_info.tag_size = len(tag_data) + len(padding)

def _convertFrames(self, std_frames, convert_list, version):
"""Maps frame imcompatibilies between ID3 v2.3 and v2.4.
"""Maps frame incompatibilities between ID3 v2.3 and v2.4.
The items in ``std_frames`` need no conversion, but the list/frames
may be edited if necessary (e.g. a converted frame replaces a frame
in the list). The items in ``convert_list`` are the frames to convert
Expand Down Expand Up @@ -1148,9 +1169,10 @@ def _convertFrames(self, std_frames, convert_list, version):
# Raise an error for frames that could not be converted.
if len(flist) != 0:
unconverted = u", ".join([f.id.decode("ascii") for f in flist])
raise TagException("Unable to covert the following frames to "
"version %s: %s" % (versionToString(version),
unconverted))
if version[0] != 1:
raise TagException("Unable to covert the following frames to "
"version %s: %s" % (versionToString(version),
unconverted))

# Some frames in converted_frames may replace/edit frames in std_frames.
for cframe in converted_frames:
Expand Down

0 comments on commit d7f1711

Please sign in to comment.