python-lzf-release-0.2.6/0000775000175000017500000000000015060250404014245 5ustar tchettchetpython-lzf-release-0.2.6/LICENSE0000664000175000017500000000275615060250404015264 0ustar tchettchetCopyright (c) 2010, Travis Parker All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. python-lzf-release-0.2.6/README.txt0000664000175000017500000000125214632640640015754 0ustar tchettchetpython-lzf: liblzf python bindings This package is just a straight translation of the C api of liblzf to python. It has two functions: compress() and decompress(). compress() accepts a string to compress and an optional maximum length for the output. If it cannot compress the string down to the requested size is to return None. The default behavior if no size is explicitly requested is to use one less than the length of the input, so the caller must always be prepared for a return value of None. decompress() accepts a string and a size in which the uncompressed result must fit. If the uncompressed version doesn't fit in the specified size then the function returns None. python-lzf-release-0.2.6/setup.py0000664000175000017500000000141714632640640015773 0ustar tchettchetfrom setuptools import setup, Extension VERSION = (0, 2, 6) setup( name="python-lzf", description="C Extension for liblzf", version=".".join(filter(None, map(str, VERSION))), author="Travis Parker", author_email="travis.parker@gmail.com", url="http://github.com/teepark/python-lzf", license="BSD", ext_modules=[Extension( 'lzf', ['lzf_module.c', 'lzf_c.c', 'lzf_d.c'], include_dirs=('.',), extra_compile_args=['-Wall'])], classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Natural Language :: English", "Programming Language :: C", "Topic :: System :: Archiving :: Compression", ] ) python-lzf-release-0.2.6/MANIFEST.in0000664000175000017500000000011115060250370015776 0ustar tchettchetinclude README.txt include LICENSE include setup.py include lzf_module.c python-lzf-release-0.2.6/lzf_module.c0000664000175000017500000000642214632640640016566 0ustar tchettchet#define PY_SSIZE_T_CLEAN #include "Python.h" #include #include "lzf.h" #if PY_MAJOR_VERSION >= 3 #define PYBYTES_FSAS PyBytes_FromStringAndSize #define PyInt_CheckExact(pyobj) 0 #define PyInt_AsLong(pyobj) 0 #else #define PYBYTES_FSAS PyString_FromStringAndSize #endif #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4 #define Py_ssize_t ssize_t #endif static PyObject * python_compress(PyObject *self, PyObject *args) { char *input, *output; Py_ssize_t inlen; PyObject *pyoutlen = Py_None; long outlen; PyObject *result; if (!PyArg_ParseTuple(args, "s#|O", &input, &inlen, &pyoutlen)) return NULL; if (pyoutlen == Py_None) outlen = inlen - 1; else if (PyInt_CheckExact(pyoutlen)) outlen = PyInt_AsLong(pyoutlen); else if (PyLong_CheckExact(pyoutlen)) outlen = PyLong_AsLong(pyoutlen); else { PyErr_SetString(PyExc_TypeError, "max_len must be an integer"); return NULL; } if (inlen == 1) outlen++; /* work around for what looks like a liblzf bug */ if (outlen <= 0) { PyErr_SetString(PyExc_ValueError, "max_len must be > 0"); return NULL; } output = (char *)malloc(outlen + 1); if (output == NULL) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } outlen = lzf_compress(input, inlen, output, outlen + 1); if (outlen) result = PYBYTES_FSAS(output, outlen); else { Py_XINCREF(Py_None); result = Py_None; } free(output); return result; } static PyObject * python_decompress(PyObject *self, PyObject *args) { char *input, *output; Py_ssize_t inlen; long outlen; PyObject *result; if (!PyArg_ParseTuple(args, "s#l", &input, &inlen, &outlen)) return NULL; if (outlen < 0) { PyErr_SetString(PyExc_ValueError, "max_len cannot be less than 0"); return NULL; } output = (char *)malloc(outlen); outlen = lzf_decompress(input, inlen, output, outlen); if (outlen) result = PYBYTES_FSAS(output, outlen); else { if (errno == EINVAL) { PyErr_SetString(PyExc_ValueError, "error in compressed data"); free(output); return NULL; } Py_XINCREF(Py_None); result = Py_None; } free(output); return result; } static PyMethodDef methods[] = { {"compress", python_compress, METH_VARARGS, "compress(input, max_length=None)\n\ \n\ return the compressed string, or None if it doesn't compress to smaller \n\ than the original\n\ \n\ takes an optional second parameter, for specifying a maximum compressed \n\ length (default is one less than the length of the original)"}, {"decompress", python_decompress, METH_VARARGS, "decompress(input, max_length)\n\ \n\ return the decompressed string\n\ \n\ will return None if the string doesn't decompress to within max_length bytes"}, {NULL, NULL, 0, NULL} }; #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef lzfmodule = { PyModuleDef_HEAD_INIT, "lzf", "", -1, methods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit_lzf(void) { PyObject *module = PyModule_Create(&lzfmodule); return module; } #else PyMODINIT_FUNC initlzf(void) { Py_InitModule("lzf", methods); } #endif python-lzf-release-0.2.6/tests.py0000664000175000017500000000302514632640640015772 0ustar tchettchetimport os import unittest import lzf class LZFTest(object): def __init__(self, *args, **kwargs): super(LZFTest, self).__init__(*args, **kwargs) self.VAL = self.VAL.encode('utf8') def compress(self, text): # lzf guarantees that even if the compressed version is longer, it is # within 104% of the original size (rounded up), so this should work return lzf.compress(text, len(text) * 2) def test_selective(self): compressed = self.compress(self.VAL) self.assertEqual(lzf.decompress(compressed, len(self.VAL) - 1), None) assert lzf.decompress(compressed, len(self.VAL)) def test_decompresses_correctly(self): compressed = self.compress(self.VAL) self.assertEqual(lzf.decompress(compressed, len(self.VAL)), self.VAL) def test_compression_negative_maxlen(self): self.assertRaises(ValueError, lzf.compress, self.VAL, -6) def test_decompression_negative_maxlen(self): c = self.compress(self.VAL) self.assertRaises(ValueError, lzf.decompress, c, -1) def test_wrong_maxlen_type(self): self.assertRaises(TypeError, lzf.compress, self.VAL, "hi there") class ShortString(LZFTest, unittest.TestCase): VAL = "this is a test" class StringWithRepetition(LZFTest, unittest.TestCase): VAL = "a longer string, repeating. " * 500 class LongStringNoRepetition(LZFTest, unittest.TestCase): VAL = open(os.path.join(os.path.dirname(__file__), "lzf_module.c")).read() if __name__ == '__main__': unittest.main()