v0.2.2 (2010-08-07)

  * setup.py, pyppd/runner.py, pyppd/pyppd-ppdfile.in: Changing version to
  0.2.2 

  * pyppd/archiver.py, README.txt: Now, instead of looking for only *.ppd in
  the directory passed as parameter, it looks also for *.ppd.gz. When found, it
  tests: does it ends with ".gz" (case-sensitive (I have to change this))? If
  so, opens with gzip. If not, opens as usual. When we archive gzipped PPDs, we
  save them uncompressed. 

  * pyppd/archiver.py: Refactoring some variable names. 

v0.2.1 (2010-08-07)

  * setup.py, pyppd/runner.py, pyppd/pyppd-ppdfile.in: Changing version to
  0.2.1 

  * pyppd/archiver.py: Updating archiver.compress() documentation. 

v0.2.0 (2010-08-07)

  * setup.py, pyppd/runner.py, pyppd/pyppd-ppdfile.in: Changing version to
  0.2.0 

  * pyppd/archiver.py: Removing useless try/except block. 

  * pyppd/pyppd-ppdfile.in, pyppd/archiver.py: Instead of creating a .tar
  archive, we simply concatenate all PPDs found in a big text file, and save
  each's start and length inside of it. Then, when we have to "cat" it, we
  decompress the text file and print only In my tests, it's around 8% faster
  than using .tar. Also, it makes it easier, in the future, to support not only
  files .ppd, but also .ppd.gz. 

  * pyppd/runner.py, pyppd/archiver.py: Rename method create_archive -> archive 

  * pyppd/archiver.py: Reorganizing methods, the most important at the top 

  * pyppd/compressor.py: Updating decompress() documentation 

  * pyppd/pyppd-ppdfile.in, pyppd/lzma_proxy.py, pyppd/compressor.py,
  pyppd/archiver.py: Renaming lzma_proxy.py to compressor.py 

  * pyppd/runner.py, pyppd/compressor.py, pyppd/archiver.py: The runner.py
  shouldn't have to use compressor.py. It should simply ask archiver.py to
  create the archive. Compression is an implementation detail of archiver. 

  * pyppd/runner.py, pyppd/pyppd-ppdfile.in: Fixing version number 0.1.0 ->
  0.1.6 

  * pyppd/ppd.py: Removing space between DeviceID's field name and content. 

  * setup.py, contrib/git2changes.py: I made git2changes which simply gets the
  commit messages and organizes them into something similar to the GNU
  ChangeLog style. But, instead of separating the commits by day, I organize
  them by version. I think this way, even as it's not standard, generates a
  file that is more useful to pyppd's users. 

  * CHANGES.txt, .gitignore: As CHANGES.txt is created from the git log, we
  have no use to maintain it under version control. 

v0.1.6 (2010-08-03)

  * setup.py: Changing version to 0.1.6 

  * MANIFEST.in: So, pyppd/pyppd-ppdfile.in gets into the distribution archive. 

  * pyppd/pyppd-ppdfile.in: As now we don't uncompress the .tar.xz archive at
  ls(), when we tested if ppd.__class__ == tarfile.TarFile, it always failed.
  Now, at the iteration, we get the key AND the value (ppd). If the key is
  ARCHIVE, we continue. 

  * ISSUES.txt: Adding Till's suggestions and some ideas to ISSUES.txt 

  * setup.py: Making setup.py executable 

v0.1.5 (2010-08-01)

  * setup.py: Adding a description and bumping version to 0.1.4 

v0.1.4 (2010-08-01)

  * setup.py: Changing version to 0.1.4 

  * README.txt: Adding instructions to install with pip 

v0.1.3 (2010-08-01)

  * setup.py: Changing version to 0.1.3 

  * pyppd/compressor.py: Instead of silently ignoring exceptions, raises them 

  * README.txt: Minor reStructuredText fixes 

v0.1.1 (2010-08-01)

  * setup.py: Renaming the license in setup.py to GPLv3 

  * setup.py: Forgot to add read() to the long_description 

  * setup.py, README.txt: Adding a README.txt and setting it as
  long_description 

  * pyppd/pyppd-ppdfile.in: When you tried ./pyppd-ppdfile cat my-ppd.ppd, it
  raised a IndexError, as it tried to "my-ppd.ppd".split(":")[1], which don't
  exists. Now, instead of trying to read the second element ([1]), we read the
  last element, which works in both cases. 

  * setup.py: Remove pyppd/test, as I am not using tests (yet) 

  * ISSUES.txt: As Gitorious don't offers us one. Maybe we should consider
  switching to github or something... 

  * pyppd/pyppd-ppdfile.in: As the file lzma_proxy.py is inserted into
  pyppd-compressor, we don't use "import lzma_proxy as lzma". So, the methods
  are in the local namespace, thus we use compress/decompress, and not
  lzma.compress/decompress. 

  * pyppd/lzma_proxy.py: Now, I need to change it's name. Lzma_proxy seems
  unnatural to me, and we already use compressor for another file. Maybe xz.py? 

  * pyppd/pyppd-ppdfile.in: We used to decompress the PPDs in load(). So, even
  if the user simply wanted to list the PPDs (which we use only the index), he
  had to decompress everything. Now, only when the user asks to cat a file, we
  decompress the PPDs. 

  * pyppd/pyppd-ppdfile.in, pyppd/compressor.py: This way, we compress 212mb to
  3.2mb, instead of 8,2mb. This makes the program a bit slower (0.2s in my
  tests), but I think it's worthy. 

  * pyppd/runner.py, pyppd/pyppd-ppdfile.in: Adding the \ to concatenate the
  multiline strings 

  * pyppd/pyppd-ppdfile.in: Checks if pyppd-ppdfile is run directly and, if so,
  run main() 

  * pyppd/pyppd-ppdfile.in: The name 'list()' is used for instantiate list
  objects. 

  * pyppd/ppd.py: Ppd: Add object inheritance 

  * pyppd/runner.py, pyppd/pyppd-ppdfile.in: Fitting to 80 columns 

  * pyppd/archiver.py: Archiver: Removes unused import 

  * pyppd/compressor.py: When we add the PPDs to the .tar file, /usr/share/ppd
  becomes usr/share/ppd. This way, we were unable to find it afterwards. Now,
  we convert every path passed as argument to absolute, and simply ignore the
  first slash when creating the index. 

  * pyppd/ppd.py: Removes the "(" and ")" from the Product line 

  * pyppd/ppd.py: Use Product instead of NickName in the 1284DeviceID fallback 

  * pyppd/pyppd-ppdfile.in, pyppd/compressor.py: It's better than the sqlite3
  solution because we can decompress and load the tar file from memory, without
  the need to write to decompress, write As tar doesn't have an index, it needs
  to do a sequential search to find the files. It might be better to use 7z
  instead. 

  * pyppd/lzma_proxy.py: Adds compress_file(path), which compresses path with
  xz binary 

  * pyppd/compressor.py: This way, sqlite3 indexes its values, making the
  selects much faster. 

  * pyppd/pyppd-ppdfile.in, pyppd/compressor.py: It's much faster to load the
  sqlite3 DB and begin issuing SQL statements than to load the .sql dump into a
  new sqlite3 DB. 

  * pyppd/pyppd-ppdfile.in, pyppd/compressor.py: cPickle uses too much memory
  when pickling/unpickling. And, as we work with large files, it becomes a
  problem. SQLite3 is more efficient in this regard. 

  * pyppd/runner.py: Fixing bug of undefined variable when running pyppd with
  unexistent directory as argument 

  * pyppd/ppd.py: This is probably wrong [1] but, as I found many PPDs which
  1284DeviceID [1]
  http://www.undocprint.org/formats/communication_protocols/ieee_1284#ieee_1284_device_
    

  * pyppd/compressor.py: Sets ppds = None when we don't need it anymore, trying
  to keep memory usage low. 

  * pyppd/ppd.py: Adding languages not found in ISO 639, but found in some PPDs 

  * pyppd/ppd.py: Converts PPD's language name to it's ISO 639 code 

  * pyppd/ppd.py, pyppd/compressor.py: When compressing, ignore the PPDs which
  couldn't be parsed. 

  * pyppd/pyppd-ppdfile.in, pyppd/ppd.py: Instead of having the PPDs names
  hardcoded with the executable's, prefix them at execution time. Also, remove
  the "./" of executable's name, when called like ./pyppd-ppdfile. 

  * setup.py, pyppd/runner.py, pyppd/pyppd-ppdfile.in, pyppd/archiver.py: Now,
  everything will be in only one file by default. When running pyppd, it'll
  parse the folder passed as argument and create, by default, pyppd-ppdfile.
  You can run it with list or cat URI to get the compressed PPDs. 

  * pyppd/runner.py: Refactoring (extract method parse_args()) 

  * pyppd/ppd.py: We don't need to save the ppd_file anymore 

  * pyppd/compressor.py: So, when loading the resulting pickle file, we don't
  need the PPD class definition. We just load a tuple with two strings. 

  * pyppd/runner.py: Adds command-line argument parsing 

  * pyppd/ppd.py, pyppd/compressor.py: PPD class now saves its PPD file in an
  attribute 

  * pyppd/lzma_proxy.py: communicate() returns a tuple (stdout, stderr).
  Returns stdout. 

  * pyppd/compressor.py: Refactoring import lzma_proxy 

  * pyppd/ppd.py, pyppd/compressor.py: The PPD class parses a string with the
  ppd, looking for its attributes. Now, instead of saving a dictionary with
  ppd_path => {size: ppd_size, start: ppd_start}, it creates a PPD object for
  each ppd, with it's attributes, so we can in the future list them as foomatic
  does. 

  * pyppd/lzma_proxy.py, pyppd/compressor.py: This way, we can fallback to
  using the xz binary, if there isn't python-lzma available. It also has the
  advantage of using the fastest, if both are available. I need to do some
  tests to check which is better. 

  * pyppd/compressor.py: Adding compressor.compress() docstring. 

  * pyppd/compressor.py: Forgot the final period. 

  * pyppd/compressor.py: Removing garbage 

  * pyppd/compressor.py: Minor typo fix 

v0.1.0 (2010-06-12)

  * setup.py, pyppd/runner.py, pyppd/compressor.py, bin/pyppd, MANIFEST.in,
  LICENSE.txt, CHANGES.txt, .gitignore: Initial release. 

