Skip to content

Commit

Permalink
Merge branch 'master' into devel
Browse files Browse the repository at this point in the history
* master:
  release prep  !wip
  fix: [display plugin] Handle comments
  new: Composer (TCOM) support (#123)
  chg: More forgiving of invalid text encoding identifiers (fixes #101)
  chg: More forgiving of bad Unicode in text frames (fixes #105)
  version bump. !wip
  fix: Fix python3 setup when system encoding is not utf-8 (#120)
  Update pytest from 3.2.4 to 3.2.5 (#122)
  Update pytest from 3.2.3 to 3.2.4 (#121)
  chg: eyeD3 cmd line helper turned nto session-scoped fixture
  Set theme jekyll-theme-slate
  fix: Help pymagic with poorly encoded filenames
  • Loading branch information
nicfit committed Nov 18, 2017
2 parents c844d5a + f0d5bf6 commit c9dbe0b
Show file tree
Hide file tree
Showing 15 changed files with 196 additions and 85 deletions.
3 changes: 0 additions & 3 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Authors
eyeD3 is written and maintained by:

* Travis Shirk <travis@pobox.com>
* nicfit <travis@pobox.com>

and has been contributed to by (ordered by date of first contribution):

Expand All @@ -31,7 +30,5 @@ and has been contributed to by (ordered by date of first contribution):
* mafro <github@mafro.net>
* Gaetano Guerriero <x.guerriero@tin.it>
* Grun Seid <grunseid@gmail.com>
* grun <grunseid@gmail.com>
* pyup.io bot <github-bot@pyup.io>
* pyup-bot <github-bot@pyup.io>
* Chris Newton <redshodan@gmail.com>
37 changes: 37 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,43 @@ Release History

.. :changelog:
v0.8.4 (2017-11-17) : The Cold Vein
-------------------------------------

New
~~~
- Composer (TCOM) support (#123)
- Check for version incompatibilities during version changes.

Changes
~~~~~~~
- More forgiving of invalid text encoding identifiers (fixes #101)
- More forgiving of bad Unicode in text frames (fixes #105)
- EyeD3 cmd line helper turned not session-scoped fixture.
- Only warn about missing grako when the plugin is used. Fixes #115.

Fix
~~~
- Fix python3 setup when system encoding is not utf-8 (#120)
<x.guerriero@tin.it>
- Fix bad frames detection in stats plugin for python3 (#113)
<x.guerriero@tin.it>
- Script exits with 0 status when called with --version/--help (#109)
<x.guerriero@tin.it>
- Help pymagic with poorly encoded filenames.
- [display plugin] Handle comments.
- [display plugin] Handle internal exception types. Fixes #118.
- IOError (nor OSError) have a message attr.

Other
~~~~~
- Set theme jekyll-theme-slate.
- Update pytest to 3.2.5 (#122) <github-bot@pyup.io>
- Update pytest-runner to 3.0 (#108) <github-bot@pyup.io>
- Update sphinx to 1.6.5 (#106) <github-bot@pyup.io>
- Update flake8 to 3.5.0 (#107) <github-bot@pyup.io>


v0.8.3 (2017-10-22) : So Alone
-------------------------------

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ pre-release: lint test changelog requirements
false; \
fi
IFS=$$'\n';\
for auth in `git authors --list`; do \
for auth in `git authors --list | sed 's/.* <\(.*\)>/\1/'`; do \
echo "Checking $$auth...";\
grep "$$auth" AUTHORS.rst || echo "* $$auth" >> AUTHORS.rst;\
done
Expand Down
1 change: 1 addition & 0 deletions docs/_config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
theme: jekyll-theme-slate
2 changes: 1 addition & 1 deletion requirements/test.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
factory-boy==2.9.2
pytest==3.2.3
pytest==3.2.5
pytest-cov==2.5.1
pytest-runner==3.0
14 changes: 7 additions & 7 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import io
import os
import re
import sys
Expand Down Expand Up @@ -31,10 +32,9 @@ def getPackageInfo():
key_remap = {"name": "pypi_name"}

# __about__
with open(os.path.join(os.path.abspath(os.path.dirname(__file__)),
"./src",
"eyed3",
"__about__.py")) as infof:
info_fpath = os.path.join(os.path.abspath(os.path.dirname(__file__)),
"src", "eyed3", "__about__.py")
with io.open(info_fpath, encoding='utf-8') as infof:
for line in infof:
for what in info_keys:
rex = re.compile(r"__{what}__\s*=\s*['\"](.*?)['\"]"
Expand Down Expand Up @@ -63,11 +63,11 @@ def getPackageInfo():
# Info
readme = ""
if os.path.exists("README.rst"):
with open("README.rst") as readme_file:
with io.open("README.rst", encoding='utf-8') as readme_file:
readme = readme_file.read()
history = ""
if os.path.exists("HISTORY.rst"):
with open("HISTORY.rst") as history_file:
with io.open("HISTORY.rst", encoding='utf-8') as history_file:
history = history_file.read().replace(".. :changelog:", "")
info_dict["long_description"] = readme + "\n\n" + history

Expand All @@ -79,7 +79,7 @@ def requirements_yaml():
reqs = {}
reqfile = os.path.join("requirements", "requirements.yml")
if os.path.exists(reqfile):
with open(reqfile) as fp:
with io.open(reqfile, encoding='utf-8') as fp:
curr = None
for line in [l for l in [l.strip() for l in fp.readlines()]
if l and not l.startswith("#")]:
Expand Down
1 change: 0 additions & 1 deletion src/eyed3/__about__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from collections import namedtuple


Expand Down
19 changes: 16 additions & 3 deletions src/eyed3/id3/frames.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class FrameException(Error):
SUBTITLE_FID = b"TIT3" # noqa
ARTIST_FID = b"TPE1" # noqa
ALBUM_ARTIST_FID = b"TPE2" # noqa
COMPOSER_FID = b"TCOM" # noqa
ALBUM_FID = b"TALB" # noqa
TRACKNUM_FID = b"TRCK" # noqa
GENRE_FID = b"TCON" # noqa
Expand Down Expand Up @@ -243,7 +244,7 @@ def encoding(self, enc):
if not isinstance(enc, bytes):
raise TypeError("encoding argument must be a byte string.")
elif not (LATIN1_ENCODING <= enc <= UTF_8_ENCODING):
raise ValueError("encoding argument must be a valid constant.")
raise ValueError("Unknown encoding value {}".format(enc))
self._encoding = enc


Expand All @@ -270,8 +271,20 @@ def text(self, txt):
def parse(self, data, frame_header):
super(TextFrame, self).parse(data, frame_header)

self.encoding = self.data[0:1]
self.text = decodeUnicode(self.data[1:], self.encoding)
try:
self.encoding = self.data[0:1]
text_data = self.data[1:]
except ValueError as err:
log.warning("{err}; using latin1".format(err=err))
self.encoding = LATIN1_ENCODING
text_data = self.data[:]

try:
self.text = decodeUnicode(text_data, self.encoding)
except UnicodeDecodeError as err:
log.warning("Error decoding text frame {fid}: {err}"
.format(fid=self.id, err=err))
self.test = u""
log.debug("TextFrame text: %s" % self.text)

def render(self):
Expand Down
17 changes: 16 additions & 1 deletion src/eyed3/id3/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,21 @@ def _setAlbumArtist(self, val):
def _getAlbumArtist(self):
return self.getTextFrame(frames.ALBUM_ARTIST_FID)

@requireUnicode(1)
def _setComposer(self, val):
self.setTextFrame(frames.COMPOSER_FID, val)

def _getComposer(self):
return self.getTextFrame(frames.COMPOSER_FID)

@property
def composer(self):
return self._getComposer()

@composer.setter
def composer(self, v):
self._setComposer(v)

@requireUnicode(1)
def _setAlbum(self, val):
self.setTextFrame(frames.ALBUM_FID, val)
Expand Down Expand Up @@ -916,7 +931,7 @@ def _checkForConversions(self, target_version):

def _render(self, version, curr_tag_size, max_padding_size):
converted_frames = []
std_frames , non_std_frames = self._checkForConversions(version)
std_frames, non_std_frames = self._checkForConversions(version)
if non_std_frames:
converted_frames = self._convertFrames(std_frames, non_std_frames,
version)
Expand Down
19 changes: 15 additions & 4 deletions src/eyed3/plugins/classic.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ def PositiveIntArg(i):
g.add_argument("--track-offset", type=int, dest="track_offset",
metavar="N", help=ARGS_HELP["--track-offset"])

g.add_argument("--composer", type=UnicodeArg, dest="composer",
metavar="STRING", help=ARGS_HELP["--composer"])
g.add_argument("-d", "--disc-num", type=PositiveIntArg, dest="disc_num",
metavar="NUM", help=ARGS_HELP["--disc-num"])
g.add_argument("-D", "--disc-total", type=PositiveIntArg,
Expand Down Expand Up @@ -575,7 +577,11 @@ def printTag(self, tag):
printMsg("%s: %s" % (boldText("title"), title))
printMsg("%s: %s" % (boldText("artist"), artist))
printMsg("%s: %s" % (boldText("album"), album))
printMsg("%s: %s" % (boldText("album artist"), tag.album_artist))
if tag.album_artist:
printMsg("%s: %s" % (boldText("album artist"),
tag.album_artist))
if tag.composer:
printMsg("%s: %s" % (boldText("composer"), tag.composer))

for date, date_label in [
(tag.release_date, "release date"),
Expand Down Expand Up @@ -737,21 +743,24 @@ def printTag(self, tag):
printMsg("\nTerms of Use (%s): %s" % (boldText("USER"),
tag.terms_of_use))

# --verbose
if self.args.verbose:
printMsg("-" * self.terminal_width)
printMsg("%d ID3 Frames:" % len(tag.frame_set))
for fid in tag.frame_set:
frames = tag.frame_set[fid]
num_frames = len(frames)
count = " x %d" % num_frames if num_frames > 1 else ""
total_bytes = 0
if not tag.isV1():
total_bytes = sum(
tuple(frame.header.data_size + frame.header.size
for frame in frames))
for frame in frames if frame.header))
else:
total_bytes = 30
printMsg("%s%s (%d bytes)" % (fid.decode("ascii"), count,
total_bytes))
if total_bytes:
printMsg("%s%s (%d bytes)" % (fid.decode("ascii"),
count, total_bytes))
printMsg("%d bytes unused (padding)" %
(tag.file_info.tag_padding_size, ))
else:
Expand Down Expand Up @@ -828,6 +837,7 @@ def handleEdits(self, tag):
self.args.tagging_date)),
("beats per minute", partial(tag._setBpm, self.args.bpm)),
("publisher", partial(tag._setPublisher, self.args.publisher)),
("composer", partial(tag._setComposer, self.args.composer)),
):
if setFunc.args[0] is not None:
printWarning("Setting %s: %s" % (what, setFunc.args[0]))
Expand Down Expand Up @@ -1169,4 +1179,5 @@ def _getTemplateKeys():
"modification times.",
"--track-offset": "Increment/decrement the track number by [-]N. "
"This option is applied after --track=N is set.",
"--composer": "Set the composer's name.",
}
14 changes: 11 additions & 3 deletions src/eyed3/plugins/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

from argparse import ArgumentTypeError

from eyed3 import id3
from eyed3 import id3, compat
from eyed3.utils import console, formatSize, formatTime
from eyed3.plugins import LoaderPlugin
try:
Expand Down Expand Up @@ -63,7 +63,7 @@ def __compile(self):
self.sub_patterns = self.__compile_asts(asts)
self.__text = None
except BaseException as parsing_error:
raise PatternCompileException(parsing_error.message)
raise PatternCompileException(compat.unicode(parsing_error))

def __compile_asts(self, asts):
patterns = []
Expand Down Expand Up @@ -315,6 +315,14 @@ def _get_output_for(self, audio_file):
return audio_file.tag.album_artist


class ComposerTagPattern(TagPattern):
NAMES = ["C", "composer"]
DESCRIPTION = "Composer"

def _get_output_for(self, audio_file):
return audio_file.tag.composer


class TitleTagPattern(TagPattern):
NAMES = ["t", "title"]
DESCRIPTION = "Title"
Expand Down Expand Up @@ -416,7 +424,7 @@ class CommentTagPattern(DescriptableTagPattern):
def _get_output_for(self, audio_file):
matching_comments = self._get_matching_elements(audio_file.tag.comments,
audio_file)
return matching_comments[0] if len(matching_comments) > 0 else None
return matching_comments[0].text if len(matching_comments) > 0 else None


class AllCommentsTagPattern(DescriptableTagPattern, PlaceholderUsagePattern):
Expand Down
6 changes: 5 additions & 1 deletion src/eyed3/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ def __init__(self):
def guess_type(self, filename):
if os.path.splitext(filename)[1] in ID3_MIME_TYPE_EXTENSIONS:
return ID3_MIME_TYPE
return self.from_file(filename)
try:
return self.from_file(filename)
except UnicodeEncodeError as enc_err:
# https://github.com/ahupp/python-magic/pull/144
return self.from_file(filename.encode("utf-8", 'surrogateescape'))


_mime_types = MagicTypes()
Expand Down
16 changes: 16 additions & 0 deletions src/test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,19 @@ def id3tag():
def image(tmpdir):
img_file = _tempCopy(DATA_D / "CypressHill3TemplesOfBoom.jpg", tmpdir)
return img_file


@pytest.fixture(scope="session")
def eyeD3():
from eyed3 import main
def func(audiofile, args, expected_retval=0, reload_version=None):
try:
args, _, config = main.parseCommandLine(args + [audiofile.path])
retval = main.main(args, config)
except SystemExit as exit:
retval = exit.code
assert retval == expected_retval
return eyed3.load(audiofile.path, tag_version=reload_version)

return func

Loading

0 comments on commit c9dbe0b

Please sign in to comment.