Commits

Travis Shirk committed dda9498 Merge

merge

  • Participants
  • Parent commits 021084b, b8a5946

Comments (0)

Files changed (15)

 *.pyc
 *.swp
 build/*
-doc/.build/*
+docs/.build/*
 .coverage
 src/eyed3/info.py
 tags
-About eyeD3
-===========
-eyeD3_ is both a command line tool and Python module for dealing with files
-containing MPEG audio and ID3 metadata.
+About
+=====
+eyeD3_ is a Python tool for working with audio files, specifically mp3 files
+containing ID3_ metadata (i.e. song info).
 
-Features include:
+It provides a command-line tool (``eyeD3``) and a Python library
+(``import eyed3``) that can be used to write your own applications or
+plugins that are callable from the command-line tool.
 
-* Plugin based command line tool for processing mp3 files and ID3 tags.
-* A default plugin for basic inspection and editing of ID3 metadata.
-* Support for ID3 versions 1.x, 2.2 (read-only), 2.3, and 2.4.
-* Parsing of MP3 header information such as version, bit rate, sample frequency,
-  and track time.
-* API for custom scripts (or new plugins) or the support for new audio and/or
-  metadata types.
+For example, to set some song information in an mp3 file called
+``song.mp3``:
+
+.. code-block:: bash
+
+  $ eyeD3 -a Nobunny -A "Love Visions" -t "I Am a Girlfried" -n 4 song.mp3
+
+With this command we've set the artist (``-a/--artist``), album
+(``-A/--album``), title (``-t/--title``), and track number
+(``-n/--track-num``) properties in the ID3 tag of the file. This is the
+standard interface that eyeD3 has always had in the past, therefore it
+is also the default plugin when no other is specified.
+
+The results of this command can be seen by running the ``eyeD3`` with no
+options.
+
+.. code-block:: bash
+
+  $ eyeD3 song.mp3
+  song.mp3	[ 3.06 MB ]
+  -------------------------------------------------------------------------
+  ID3 v2.4:
+  title: I Am a Girlfried
+  artist: Nobunny
+  album: Love Visions
+  track: 4		
+  -------------------------------------------------------------------------
+  
+The same can be accomplished using Python.
+
+.. code-block:: python
+
+  import eyed3
+
+  audiofile = eyed3.load("song.mp3")
+  audiofile.tag.artist = u"Nobunny"
+  audiofile.tag.album = u"Love Visions"
+  audiofile.tag.title = u"I Am a Girlfried"
+  audiofile.tag.track_num = 4
+
+  audiofile.tag.save()
 
 eyeD3_ is written and maintained by `Travis Shirk`_ and is licensed under
 version 2 of the GPL_.
 
-Get eyeD3
-=========
+Features
+========
+
+* Python package for writing application and/or plugins.
+* Command-line tool driver script that supports plugins.
+  viewer/editor interface.
+* Easy editing/viewing of audio metadata from the command-line, using the
+  'classic' plugin.
+* Support for ID3 versions 1.x, 2.2 (read-only), 2.3, and 2.4.
+* Support for the MP3 audio format exposing details such as play time, bit
+  rate, sampling frequency, etc.
+* Abstract design allowing future support for different audio formats and
+  metadata containers.
+
+
+Get Started
+===========
+
+Python 2.7 is required.
+
+The easiest way to install eyeD3 is to use ``pip``:
+
+.. code-block:: bash
+
+  # pip install eyeD3
+
 .. note::
-  Versions of eyeD3 < 0.7 are NOT API compatible. The command line tool is
-  mostly compatible but may differ slightly in interface.
+  This may require root access.
 
-Supports Python 2.7.
+For alternate installation instructions and more complete documentation see
+http://eyeD3.nicfit.net/
 
-Download the latest release from `Python Package Index`_, or previous versions
-from the `release archive`_. To develop eyeD3 you should clone
-`the repository`_.
-
-Read the documentation online at http://eyeD3.nicfit.net/
-
-Post feedback and issues on the `bug tracker`_, or `mailing list`_.
-
+Post feedback and/or defects on the `issue tracker`_, or `mailing list`_.
 
 .. _eyeD3: http://eyeD3.nicfit.net/
 .. _Travis Shirk: travis@pobox.com
-.. _Python Package Index: http://pypi.python.org/pypi/eyeD3
-.. _the repository: https://bitbucket.org/nicfit/eyed3
-.. _bug tracker: https://bitbucket.org/nicfit/eyed3/issues?status=new&status=open
+.. _issue tracker: https://bitbucket.org/nicfit/eyed3/issues?status=new&status=open
 .. _mailing list: https://groups.google.com/forum/?fromgroups#!forum/eyed3-users
 .. _GPL: https://bitbucket.org/nicfit/eyed3/raw/6dfa97d26479/COPYING
-.. _release archive: http://eyed3.nicfit.net/releases/
+.. _ID3: http://id3.org/
 
-
-.. vim: set filetype=rst

bin/cli_examples.sh

 #!/bin/bash
 
 # [[[section SETUP]]]
-rm -f example.mp3
-touch example.mp3
-ls -o example.mp3
+rm -f example.id3
+touch example.id3
+ls -o example.id3
 # [[[endsection]]]
 
 # [[[section ART_TIT_SET]]]
-eyeD3 --artist="Token Entry" --title="Entities" example.mp3
+eyeD3 --artist="Token Entry" --title="Entities" example.id3 -Q
 # [[[endsection]]]
 
 # [[[section ALB_YR_SET]]]
-eyeD3 -A "Jaybird" -Y 1987 example.mp3
-eyeD3 -G "Hardcore" example.mp3
+eyeD3 -A "Jaybird" -Y 1987 example.id3 -Q
+eyeD3 -G "Hardcore" example.id3 -Q
+eyeD3 example.id3
 # [[[endsection]]]
 
 
 # [[[section CLEAR_SET]]]
-eyeD3 --genre="" example.mp3
+eyeD3 --genre="" example.id3
 # [[[endsection]]]
 
 # [[[section ALL]]]
 # Set an artist value in the ID3 v1 tag
-eyeD3 -1 example.mp3 -a id3v1
+eyeD3 -1 example.id3 -a id3v1
 # The file now has a v1 and v2 tag, change the v2 artist
-eyeD3 -2 example.mp3 -a id3v2
+eyeD3 -2 example.id3 -a id3v2
 
 # Take all the values from v2.4 tag (the default) and set them in the v1 tag.
-eyeD3 -2 --to-v1.1 example.mp3
+eyeD3 -2 --to-v1.1 example.id3
 # Take all the values from v1 tag and convert to ID3 v2.3
-eyeD3 -1 --to-v2.3 example.mp3
+eyeD3 -1 --to-v2.3 example.id3
 
 # Remove all the tags
-eyeD3 --remove-all example.mp3
+eyeD3 --remove-all example.id3
 # [[[endsection]]]

docs/.static/.keepme

Empty file removed.

docs/.templates/.keepme

Empty file removed.

docs/_static/.keepme

Empty file added.

docs/_static/rtd.css

+/*
+ * rtd.css
+ * ~~~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- sphinxdoc theme.  Originally created by
+ * Armin Ronacher for Werkzeug.
+ *
+ * Customized for ReadTheDocs by Eric Pierce & Eric Holscher
+ *
+ * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/* RTD colors
+ * light blue: #e8ecef
+ * medium blue: #8ca1af
+ * dark blue: #465158
+ * dark grey: #444444
+ *
+ * white hover: #d1d9df;
+ * medium blue hover: #697983;
+ * green highlight: #8ecc4c
+ * light blue (project bar): #e8ecef
+ */
+
+@import url("basic.css");
+
+/* PAGE LAYOUT -------------------------------------------------------------- */
+
+body {
+    font: 100%/1.5 "ff-meta-web-pro-1","ff-meta-web-pro-2",Arial,"Helvetica Neue",sans-serif; 
+    text-align: center;
+    color: black;
+    background-color: #465158;
+    padding: 0;
+    margin: 0;
+}
+
+div.document {
+    text-align: left;
+    background-color: #e8ecef;
+}
+
+div.bodywrapper {
+    background-color: #ffffff;
+    border-left: 1px solid #ccc;
+    border-bottom: 1px solid #ccc;
+    margin: 0 0 0 16em;
+}
+
+div.body {
+    margin: 0;
+    padding: 0.5em 1.3em;
+    max-width: 55em;
+    min-width: 20em;
+}
+
+div.related {
+    font-size: 1em;
+    background-color: #465158;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+    background-color: #e8ecef;
+}
+
+
+/* HEADINGS --------------------------------------------------------------- */
+
+h1 {
+    margin: 0;
+    padding: 0.7em 0 0.3em 0;
+    font-size: 1.5em;
+    line-height: 1.15;
+    color: #111;
+    clear: both;
+}
+
+h2 {
+    margin: 2em 0 0.2em 0;
+    font-size: 1.35em;
+    padding: 0;
+    color: #465158;
+}
+
+h3 {
+    margin: 1em 0 -0.3em 0;
+    font-size: 1.2em;
+    color: #6c818f;
+}
+
+div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
+    color: black;
+}
+
+h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
+    display: none;
+    margin: 0 0 0 0.3em;
+    padding: 0 0.2em 0 0.2em;
+    color: #aaa !important;
+}
+
+h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
+h5:hover a.anchor, h6:hover a.anchor {
+    display: inline;
+}
+
+h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
+h5 a.anchor:hover, h6 a.anchor:hover {
+    color: #777;
+    background-color: #eee;
+}
+
+
+/* LINKS ------------------------------------------------------------------ */
+
+/* Normal links get a pseudo-underline */
+a {
+    color: #444;
+    text-decoration: none;
+    border-bottom: 1px solid #ccc;
+}
+
+/* Links in sidebar, TOC, index trees and tables have no underline */
+.sphinxsidebar a,
+.toctree-wrapper a,
+.indextable a,
+#indices-and-tables a {
+    color: #444;
+    text-decoration: none;
+    border-bottom: none;
+}
+
+/* Most links get an underline-effect when hovered */
+a:hover,
+div.toctree-wrapper a:hover,
+.indextable a:hover,
+#indices-and-tables a:hover {
+    color: #111;
+    text-decoration: none;
+    border-bottom: 1px solid #111;
+}
+
+/* Footer links */
+div.footer a {
+    color: #86989B;
+    text-decoration: none;
+    border: none;
+}
+div.footer a:hover {
+    color: #a6b8bb;
+    text-decoration: underline;
+    border: none;
+}
+
+/* Permalink anchor (subtle grey with a red hover) */
+div.body a.headerlink {
+    color: #ccc;
+    font-size: 1em;
+    margin-left: 6px;
+    padding: 0 4px 0 4px;
+    text-decoration: none;
+    border: none;
+}
+div.body a.headerlink:hover {
+    color: #c60f0f;
+    border: none;
+}
+
+
+/* NAVIGATION BAR --------------------------------------------------------- */
+
+div.related ul {
+    height: 2.5em;
+}
+
+div.related ul li {
+    margin: 0;
+    padding: 0.65em 0;
+    float: left;
+    display: block;
+    color: white; /* For the >> separators */
+    font-size: 0.8em;
+}
+
+div.related ul li.right {
+    float: right;
+    margin-right: 5px;
+    color: transparent; /* Hide the | separators */
+}
+
+/* "Breadcrumb" links in nav bar */
+div.related ul li a {
+    order: none;
+    background-color: inherit;
+    font-weight: bold;
+    margin: 6px 0 6px 4px;
+    line-height: 1.75em;
+    color: #ffffff;
+    padding: 0.4em 0.8em;
+    border: none;
+    border-radius: 3px;
+}
+/* previous / next / modules / index links look more like buttons */
+div.related ul li.right a {
+    margin: 0.375em 0;
+    background-color: #697983;
+    text-shadow: 0 1px rgba(0, 0, 0, 0.5);
+    border-radius: 3px;
+    -webkit-border-radius: 3px;
+    -moz-border-radius: 3px;
+}
+/* All navbar links light up as buttons when hovered */
+div.related ul li a:hover {
+    background-color: #8ca1af;
+    color: #ffffff;
+    text-decoration: none;
+    border-radius: 3px;
+    -webkit-border-radius: 3px;
+    -moz-border-radius: 3px;
+}
+/* Take extra precautions for tt within links */
+a tt,
+div.related ul li a tt {
+    background: inherit !important;
+    color: inherit !important;
+}
+
+
+/* SIDEBAR ---------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+    padding: 0;
+}
+
+div.sphinxsidebar {
+    margin: 0;
+    margin-left: -100%;
+    float: left;
+    top: 3em;
+    left: 0;
+    padding: 0 1em;
+    width: 14em;
+    font-size: 1em;
+    text-align: left;
+    background-color: #e8ecef;
+}
+
+div.sphinxsidebar img {
+    max-width: 12em;
+}
+
+div.sphinxsidebar h3, div.sphinxsidebar h4 {
+    margin: 1.2em 0 0.3em 0;
+    font-size: 1em;
+    padding: 0;
+    color: #222222;
+    font-family: "ff-meta-web-pro-1", "ff-meta-web-pro-2", "Arial", "Helvetica Neue", sans-serif;
+}
+
+div.sphinxsidebar h3 a {
+    color: #444444;
+}
+
+div.sphinxsidebar ul,
+div.sphinxsidebar p {
+    margin-top: 0;
+    padding-left: 0;
+    line-height: 130%;
+    background-color: #e8ecef;
+}
+
+/* No bullets for nested lists, but a little extra indentation */
+div.sphinxsidebar ul ul {
+    list-style-type: none;
+    margin-left: 1.5em;
+    padding: 0;
+}
+
+/* A little top/bottom padding to prevent adjacent links' borders
+ * from overlapping each other */
+div.sphinxsidebar ul li {
+    padding: 1px 0;
+}
+
+/* A little left-padding to make these align with the ULs */
+div.sphinxsidebar p.topless {
+    padding-left: 0 0 0 1em;
+}
+
+/* Make these into hidden one-liners */
+div.sphinxsidebar ul li,
+div.sphinxsidebar p.topless {
+    white-space: nowrap;
+    overflow: hidden;
+}
+/* ...which become visible when hovered */
+div.sphinxsidebar ul li:hover,
+div.sphinxsidebar p.topless:hover {
+    overflow: visible;
+}
+
+/* Search text box and "Go" button */
+#searchbox {
+    margin-top: 2em;
+    margin-bottom: 1em;
+    background: #ddd;
+    padding: 0.5em;
+    border-radius: 6px;
+    -moz-border-radius: 6px;
+    -webkit-border-radius: 6px;
+}
+#searchbox h3 {
+    margin-top: 0;
+}
+
+/* Make search box and button abut and have a border */
+input,
+div.sphinxsidebar input {
+    border: 1px solid #999;
+    float: left;
+}
+
+/* Search textbox */
+input[type="text"] {
+    margin: 0;
+    padding: 0 3px;
+    height: 20px;
+    width: 144px;
+    border-top-left-radius: 3px;
+    border-bottom-left-radius: 3px;
+    -moz-border-radius-topleft: 3px;
+    -moz-border-radius-bottomleft: 3px;
+    -webkit-border-top-left-radius: 3px;
+    -webkit-border-bottom-left-radius: 3px;
+}
+/* Search button */
+input[type="submit"] {
+    margin: 0 0 0 -1px; /* -1px prevents a double-border with textbox */
+    height: 22px;
+    color: #444;
+    background-color: #e8ecef;
+    padding: 1px 4px;
+    font-weight: bold;
+    border-top-right-radius: 3px;
+    border-bottom-right-radius: 3px;
+    -moz-border-radius-topright: 3px;
+    -moz-border-radius-bottomright: 3px;
+    -webkit-border-top-right-radius: 3px;
+    -webkit-border-bottom-right-radius: 3px;
+}
+input[type="submit"]:hover {
+    color: #ffffff;
+    background-color: #8ecc4c;
+}
+
+div.sphinxsidebar p.searchtip {
+    clear: both;
+    padding: 0.5em 0 0 0;
+    background: #ddd;
+    color: #666;
+    font-size: 0.9em;
+}
+
+/* Sidebar links are unusual */
+div.sphinxsidebar li a,
+div.sphinxsidebar p a {
+    background: #e8ecef; /* In case links overlap main content */
+    border-radius: 3px;
+    -moz-border-radius: 3px;
+    -webkit-border-radius: 3px;
+    border: 1px solid transparent; /* To prevent things jumping around on hover */
+    padding: 0 5px 0 5px;
+}
+div.sphinxsidebar li a:hover,
+div.sphinxsidebar p a:hover {
+    color: #111;
+    text-decoration: none;
+    border: 1px solid #888;
+}
+
+/* Tweak any link appearing in a heading */
+div.sphinxsidebar h3 a {
+}
+
+
+
+
+/* OTHER STUFF ------------------------------------------------------------ */
+
+cite, code, tt {
+    font-family: 'Consolas', 'Deja Vu Sans Mono',
+                 'Bitstream Vera Sans Mono', monospace;
+    font-size: 0.95em;
+    letter-spacing: 0.01em;
+}
+
+tt {
+    background-color: #f2f2f2;
+    color: #444;
+}
+
+tt.descname, tt.descclassname, tt.xref {
+    border: 0;
+}
+
+hr {
+    border: 1px solid #abc;
+    margin: 2em;
+}
+
+pre, #_fontwidthtest {
+    font-family: 'Consolas', 'Deja Vu Sans Mono',
+                 'Bitstream Vera Sans Mono', monospace;
+    margin: 1em 2em;
+    font-size: 0.95em;
+    letter-spacing: 0.015em;
+    line-height: 120%;
+    padding: 0.5em;
+    border: 1px solid #ccc;
+    background-color: #eee;
+    border-radius: 6px;
+    -moz-border-radius: 6px;
+    -webkit-border-radius: 6px;
+}
+
+pre a {
+    color: inherit;
+    text-decoration: underline;
+}
+
+td.linenos pre {
+    padding: 0.5em 0;
+}
+
+div.quotebar {
+    background-color: #f8f8f8;
+    max-width: 250px;
+    float: right;
+    padding: 2px 7px;
+    border: 1px solid #ccc;
+}
+
+div.topic {
+    background-color: #f8f8f8;
+}
+
+table {
+    border-collapse: collapse;
+    margin: 0 -0.5em 0 -0.5em;
+}
+
+table td, table th {
+    padding: 0.2em 0.5em 0.2em 0.5em;
+}
+
+
+/* ADMONITIONS AND WARNINGS ------------------------------------------------- */
+
+/* Shared by admonitions and warnings */
+div.admonition, div.warning {
+    font-size: 0.9em;
+    margin: 2em;
+    padding: 0;
+    /*
+    border-radius: 6px;
+    -moz-border-radius: 6px;
+    -webkit-border-radius: 6px;
+    */
+}
+div.admonition p, div.warning p {
+    margin: 0.5em 1em 0.5em 1em;
+    padding: 0;
+}
+div.admonition pre, div.warning pre {
+    margin: 0.4em 1em 0.4em 1em;
+}
+div.admonition p.admonition-title,
+div.warning p.admonition-title {
+    margin: 0;
+    padding: 0.1em 0 0.1em 0.5em;
+    color: white;
+    font-weight: bold;
+    font-size: 1.1em;
+    text-shadow: 0 1px rgba(0, 0, 0, 0.5);
+}
+div.admonition ul, div.admonition ol,
+div.warning ul, div.warning ol {
+    margin: 0.1em 0.5em 0.5em 3em;
+    padding: 0;
+}
+
+
+/* Admonitions only */
+div.admonition {
+    border: 1px solid #609060;
+    background-color: #e9ffe9;
+}
+div.admonition p.admonition-title {
+    background-color: #70A070;
+    border-bottom: 1px solid #609060;
+}
+
+
+/* Warnings only */
+div.warning {
+    border: 1px solid #900000;
+    background-color: #ffe9e9;
+}
+div.warning p.admonition-title {
+    background-color: #b04040;
+    border-bottom: 1px solid #900000;
+}
+
+
+
+div.versioninfo {
+    margin: 1em 0 0 0;
+    border: 1px solid #ccc;
+    background-color: #DDEAF0;
+    padding: 8px;
+    line-height: 1.3em;
+    font-size: 0.9em;
+}
+
+.viewcode-back {
+    font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+                 'Verdana', sans-serif;
+}
+
+div.viewcode-block:target {
+    background-color: #f4debf;
+    border-top: 1px solid #ac9;
+    border-bottom: 1px solid #ac9;
+}
+
+dl {
+    margin: 1em 0 2.5em 0;
+}
+
+/* Highlight target when you click an internal link */
+dt:target {
+    background: #ffe080;
+}
+/* Don't highlight whole divs */
+div.highlight {
+    background: transparent;
+}
+/* But do highlight spans (so search results can be highlighted) */
+span.highlight {
+    background: #ffe080;
+}
+
+div.footer {
+    background-color: #465158;
+    color: #eeeeee;
+    padding: 0 2em 2em 2em;
+    clear: both;
+    font-size: 0.8em;
+    text-align: center;
+}
+
+p {
+    margin: 0.8em 0 0.5em 0;
+}
+
+.section p img {
+    margin: 1em 2em;
+}
+
+
+/* MOBILE LAYOUT -------------------------------------------------------------- */
+
+@media screen and (max-width: 600px) {
+    
+    h1, h2, h3, h4, h5 {
+        position: relative;
+    }
+
+    ul {
+        padding-left: 1.75em;
+    }
+
+    div.bodywrapper a.headerlink, #indices-and-tables h1 a {
+        color: #e6e6e6;
+        font-size: 80%;
+        float: right;
+        line-height: 1.8;
+        position: absolute;
+        right: -0.7em;
+        visibility: inherit;
+    }
+
+    div.bodywrapper h1 a.headerlink, #indices-and-tables h1 a {
+        line-height: 1.5;
+    }
+
+    pre {
+        font-size: 0.7em;
+        overflow: auto;
+        word-wrap: break-word;
+        white-space: pre-wrap;
+    }
+
+    div.related ul {
+        height: 2.5em;
+        padding: 0;
+        text-align: left;
+    }
+
+    div.related ul li {
+        clear: both;
+        color: #465158;
+        padding: 0.2em 0;
+    }
+
+    div.related ul li:last-child {
+        border-bottom: 1px dotted #8ca1af;
+        padding-bottom: 0.4em;
+        margin-bottom: 1em;
+        width: 100%;
+    }
+
+    div.related ul li a {
+        color: #465158;
+        padding-right: 0;
+    }
+
+    div.related ul li a:hover {
+        background: inherit;
+        color: inherit;
+    }
+
+    div.related ul li.right {
+        clear: none;
+        padding: 0.65em 0;
+        margin-bottom: 0.5em;
+    }
+
+    div.related ul li.right a {
+        color: #fff;
+        padding-right: 0.8em;
+    }
+
+    div.related ul li.right a:hover {
+        background-color: #8ca1af;
+    }
+
+    div.body {
+        clear: both;
+        min-width: 0;
+        word-wrap: break-word;
+    }
+
+    div.bodywrapper {
+        margin: 0 0 0 0;
+    }
+
+    div.sphinxsidebar {
+        float: none;
+        margin: 0;
+        width: auto;
+    }
+
+    div.sphinxsidebar input[type="text"] {
+        height: 2em;
+        line-height: 2em;
+        width: 70%;
+    }
+
+    div.sphinxsidebar input[type="submit"] {
+        height: 2em;
+        margin-left: 0.5em;
+        width: 20%;
+    }
+
+    div.sphinxsidebar p.searchtip {
+        background: inherit;
+        margin-bottom: 1em;
+    }
+
+    div.sphinxsidebar ul li, div.sphinxsidebar p.topless {
+        white-space: normal;
+    }
+
+    .bodywrapper img {
+        display: block;
+        margin-left: auto;
+        margin-right: auto;
+        max-width: 100%;
+    }
+
+    div.documentwrapper {
+        float: none;
+    }
+
+    div.admonition, div.warning, pre, blockquote {
+        margin-left: 0em;
+        margin-right: 0em;
+    }
+
+    .body p img {
+        margin: 0;
+    }
+
+    #searchbox {
+        background: transparent;
+    }
+
+    .related:not(:first-child) li {
+        display: none;
+    }
+
+    .related:not(:first-child) li.right {
+        display: block;
+    }
+
+    div.footer {
+        padding: 1em;
+    }
+
+    .rtd_doc_footer .badge {
+        float: none;
+        margin: 1em auto;
+        position: static;
+    }
+
+    .rtd_doc_footer .badge.revsys-inline {
+        margin-right: auto;
+        margin-bottom: 2em;
+    }
+
+    table.indextable {
+        display: block;
+        width: auto; 
+    }
+
+    .indextable tr {
+        display: block;
+    }
+
+    .indextable td {
+        display: block;
+        padding: 0;
+        width: auto !important;
+    }
+
+    .indextable td dt {
+        margin: 1em 0;
+    }
+
+    ul.search {
+        margin-left: 0.25em;
+    }
+
+    ul.search li div.context {
+        font-size: 90%;
+        line-height: 1.1;
+        margin-bottom: 1;
+        margin-left: 0;
+    }
+
+}

docs/_templates/.keepme

Empty file added.

docs/changelog.rst

   New Features:
     * Command line script ``eyeD3`` now supports plugins. The default plugin
       is the classic interface for tag reading and editing.
-    * Example plugins for listing valid genre names, mime-type stats, and
-      display of low-level mp3 details.
+    * A plugin for writing NFO files.
+    * Example plugins for listing valid genres, library stats, mime-types, and
+      lame (xing) header information.
     * Module name is now ``eyed3`` (all lower case) to be more standards
       conforming.
-    * New property based interface for tag data.
-    * Improved ID3 date frame support.
+    * New ``Tag`` interface based on properties.
+    * Improved ID3 date frame support and 2.3<->2.4 conversion, and better
+      conversions, in general.
     * Python Package Index friendly, and installable with 'pip'.
     * Improved mime-type detection.
     * Improved unicode support.
+    * Support for config files to contain common options.
 
 **0.6.18** - 11.25.2011 (Nobunny loves you)
   New features:
 # serve to show the default.
 
 import sys, os
+from datetime import datetime
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
               'sphinx.ext.viewcode', 'sphinx.ext.extlinks']
 
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ['.templates']
+templates_path = ['_templates']
 
 # The suffix of source filenames.
 source_suffix = '.rst'
 master_doc = 'index'
 
 # General information about the project.
-project = u'eyeD3'
-copyright = u'2012, Travis Shirk'
+sys.path.append(os.path.join(os.getcwd(), ".."))
+os.chdir("..")
+import pavement
+os.chdir("docs")
+
+project = pavement.PROJECT
+copyright = u'%d, %s' % (datetime.now().year, pavement.AUTHOR)
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
-with open("../version", "r") as _version:
-    _version = _version.read().strip("\n")
-    version, release = _version.split("-")
+version, release = pavement.VERSION.split("-")
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
+#html_theme = 'nature'
 html_theme = 'default'
-html_theme = 'nature'
+html_style = "rtd.css"
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['.static']
+html_static_path = ['_static']
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
+# -*- coding: utf-8 -*-
+################################################################################
+#  Copyright (C) 2012  Travis Shirk <travis@pobox.com>
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+################################################################################
+import os
+from fabric.api import run, put
+from pavement import SRC_DIST_TGZ, DOC_DIST, MD5_DIST, SRC_DIST_ZIP
+
+RELEASE_D = "~/www/eyeD3/releases"
+
+def host_type():
+    run('uname -a')
+
+def deploy_sdist():
+    put("./dist/%s" % SRC_DIST_TGZ, RELEASE_D)
+    put("./dist/%s" % SRC_DIST_ZIP, RELEASE_D)
+    put("./dist/%s.md5" % os.path.splitext(SRC_DIST_TGZ)[0], RELEASE_D)
+
+def deploy_docs():
+    put("./dist/%s" % DOC_DIST, "~")
+    run("tar xzf eyeD3_docs-0.7.0-rc1.tgz -C ./www/eyeD3 --strip-components=1")
+
+def deploy():
+    deploy_sdist()
+    deploy_docs()
+
 except:
     paverutils = None
 
-PROJECT = "eyeD3"
-VERSION = open("version", "r").read().strip('\n')
+PROJECT = u"eyeD3"
+VERSION = "0.7.0-rc1"
+
 LICENSE = open("COPYING", "r").read().strip('\n')
 DESCRIPTION = "Audio data toolkit (ID3 and MP3)"
 LONG_DESCRIPTION = """
 URL = "http://eyeD3.nicfit.net"
 AUTHOR = "Travis Shirk"
 AUTHOR_EMAIL = "travis@pobox.com"
-SRC_DIST = "%s-%s.tgz" % (PROJECT, VERSION)
+SRC_DIST_TGZ = "%s-%s.tgz" % (PROJECT, VERSION)
+SRC_DIST_ZIP = "%s.zip" % os.path.splitext(SRC_DIST_TGZ)[0]
 DOC_DIST = "%s_docs-%s.tgz" % (PROJECT, VERSION)
+MD5_DIST = "%s.md5" % os.path.splitext(SRC_DIST_TGZ)[0]
 DOC_BUILD_D = "docs/.build"
 
 PACKAGE_DATA = paver.setuputils.find_package_data("src/eyed3",
         author=AUTHOR, maintainer=AUTHOR,
         author_email=AUTHOR_EMAIL, maintainer_email=AUTHOR_EMAIL,
         url=URL,
-        download_url="%s/releases/%s" % (URL, SRC_DIST),
+        download_url="%s/releases/%s" % (URL, SRC_DIST_TGZ),
         license=license,
         package_dir={"": "src" },
         packages=setuptools.find_packages("src",
         keywords=("id3", "mp3", "python"),
         scripts=["bin/eyeD3"],
         package_data=PACKAGE_DATA,
-   ),
+    ),
 
-   sphinx=Bunch(
+    sdist=Bunch(
+        formats="gztar,zip",
+    ),
+
+    sphinx=Bunch(
         docroot=os.path.split(DOC_BUILD_D)[0],
         builddir=os.path.split(DOC_BUILD_D)[1],
         builder='html',
         template_args = {},
-   ),
+    ),
 
-   cog=Bunch(
+    cog=Bunch(
        beginspec='{{{cog',
        endspec='}}}',
        endoutput='{{{end}}}',
        includedir=path(__file__).abspath().dirname(),
-   ),
+    ),
 
-   test=Bunch(
+    test=Bunch(
        debug=False,
        coverage=False,
-   ),
+    ),
 )
 
 @task
 def sdist(options):
     '''Make a source distribution'''
     cwd = os.getcwd()
-    dist_name = os.path.splitext(SRC_DIST)[0]
     try:
         os.chdir("dist")
         # Rename to .tgz
-        sh("mv %s.tar.gz %s" % (dist_name, SRC_DIST))
-        sh("md5sum %s > %s.md5" % (SRC_DIST, dist_name))
+        sh("mv %s.tar.gz %s" % (os.path.splitext(SRC_DIST_TGZ)[0],
+                                SRC_DIST_TGZ))
+        sh("md5sum %s >> %s" % (SRC_DIST_TGZ, MD5_DIST))
+        sh("md5sum %s >> %s" % (SRC_DIST_ZIP, MD5_DIST))
     finally:
         os.chdir(cwd)
 
 def test_dist():
     '''Makes a dist package, unpacks it, and tests it.'''
     cwd = os.getcwd()
-    pkg_d = os.path.splitext(SRC_DIST)[0]
+    pkg_d = os.path.splitext(SRC_DIST_TGZ)[0]
     try:
         os.chdir("./dist")
-        sh("tar xzf %s" % SRC_DIST)
+        sh("tar xzf %s" % SRC_DIST_TGZ)
 
         os.chdir(pkg_d)
         # Copy tests into src pkg
     finally:
         os.chdir(cwd)
 
+
 @task
 @needs("distclean", "test_dist", "docdist", "changelog")
 def release():
     checklist()
 
+
 @task
 @needs("docs")
 def docdist():
         os.chdir(DOC_BUILD_D)
         sh("tar czvf ../../dist/%s html" % DOC_DIST)
         os.chdir("%s/dist" % cwd)
-        sh("md5sum %s > %s.md5" % (DOC_DIST, os.path.splitext(DOC_DIST)[0]))
+        sh("md5sum %s >> %s" % (DOC_DIST, MD5_DIST))
     finally:
         os.chdir(cwd)
 
 Release Procedure
 =================
 
+- hg up stable
 - clean working copy / use sandbox
-- Set version in ``version`` file.
+- Set version in ``pavement.py``
 - Update doc/changelog.rst with date, features, etc.
-- paver release
+- paver release uncog
+- hg tag v%(VERSION)s
 - hg commit -m 'prep for release'
 
-- hg tag
-- hg merge to 'default'
+# Merge to default
+- hg up default
+- hg merge stable
 
-- Upload source dist to http://eyed3.nicfit.net/releases
-- Upload docs to http://eyed3.nicfit.net/
+- Update eyeD3.nicfit.net
+  fab -H melvins.nicfit.net:222 deploy
 - Announce to mailing list
 - Announce to FreshMeat
 - Upload to Python Index (paver upload?)
 
 - ebuild
-""")
+""" % globals())
 
 def cog_pluginHelp(name):
     from string import Template
                 else:
                     cmd_line = cmd
 
-                cmd_line = (' ' * 2) + cmd_line
-                self.cog.gen.out(cmd_line + "\n")
+                cmd_line = '\n' + (' ' * 2) + cmd_line
+                self.cog.gen.out(cmd_line)
                 output = sh(cmd, capture=True)
                 if output:
                     self.cog.gen.out("\n")

src/eyed3/id3/headers.py

     def rev_version(self):
         return self._version[2]
 
-    ##
-    # \param f File pointer positioned at the start of the ID3 v2 header.
-    # \throws TagException Thrown if the header is invalid
-    # \returns True if a tag header was parsed, False if not.
     def parse(self, f):
+        '''Parse an ID3 v2 header starting at the current position of ``f``.
+        If a header is parsed ``True`` is returned, otherwise ``False``. If
+        a header is found but malformed an ``eyed3.id3.tag.TagException`` is
+        thrown.
+        '''
         from .tag import TagException
 
         self.clear()
 
     # Only call this when you *know* there is an extened header.
     def parse(self, fp, version):
+        '''Parse an ID3 v2 extended header starting at the current position
+        of ``fp`` and per the format defined by ``version``. This method
+        should only be called when the presence of an extended header is known
+        since it moves the file position. If a header is found but malformed
+        an ``eyed3.id3.tag.TagException`` is thrown. The return value is
+        ``None``.
+        '''
         from .tag import TagException
         assert(version[0] == 2)
 
                            frame_header.data_length_indicator))
             if (frame_header.minor_version >= 4 and frame_header.compressed and
                    not frame_header.data_length_indicator):
-                raise FrameException("Invalid frame; compressed with no data "
-                                     "length indicator")
+                core.parseError(FrameException("Invalid frame; compressed with "
+                                               "no data length indicator"))
 
             return frame_header
         elif frame_id == '\x00\x00\x00\x00':

src/eyed3/id3/tag.py

             fileobj = file(filename, "rb")
             close_file = True
         else:
-            raise TagException("Invalid type: %s" % str(type(fileobj)))
+            raise ValueError("Invalid type: %s" % str(type(fileobj)))
 
         self.file_info = FileInfo(filename)
 

version

-0.8.0-alpha