diff --git a/.gitignore b/.gitignore index af3cbac..f0d6df7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ .cache +.eggs +.tox/ dist/ ffmpeg/tests/sample_data/dummy2.mp4 -venv +ffmpeg_python.egg-info/ +venv* diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..e2d8f77 --- /dev/null +++ b/.python-version @@ -0,0 +1,5 @@ +3.3.6 +3.4.6 +3.5.3 +3.6.1 +jython-2.7.0 diff --git a/.travis.yml b/.travis.yml index 4442bf1..f1863cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,36 @@ language: python before_install: - - curl -O https://johnvansickle.com/ffmpeg/releases/ffmpeg-3.3.1-64bit-static.tar.xz - - tar Jxf ffmpeg-3.3.1-64bit-static.tar.xz + - > + [ -f ffmpeg-3.3.1-64bit-static/ffmpeg ] || ( + curl -O https://johnvansickle.com/ffmpeg/releases/ffmpeg-3.3.1-64bit-static.tar.xz && + tar Jxf ffmpeg-3.3.1-64bit-static.tar.xz + ) +matrix: + include: + - python: 2.7 + env: + - TOX_ENV=py27 + - python: 3.3 + env: + - TOX_ENV=py33 + - python: 3.4 + env: + - TOX_ENV=py34 + - python: 3.5 + env: + - TOX_ENV=py35 + - python: 3.6 + env: + - TOX_ENV=py36 + - python: pypy + env: + - TOX_ENV=pypy install: - - pip install -r requirements.txt + - pip install tox script: - export PATH=$(readlink -f ffmpeg-3.3.1-64bit-static):$PATH - - py.test + - tox -e $TOX_ENV +cache: + directories: + - .tox + - ffmpeg-3.3.1-64bit-static diff --git a/ffmpeg/__init__.py b/ffmpeg/__init__.py index ff5c064..1953609 100644 --- a/ffmpeg/__init__.py +++ b/ffmpeg/__init__.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals from . import _filters, _ffmpeg, _run from ._filters import * from ._ffmpeg import * diff --git a/ffmpeg/_ffmpeg.py b/ffmpeg/_ffmpeg.py index c9c7f19..0d0a549 100644 --- a/ffmpeg/_ffmpeg.py +++ b/ffmpeg/_ffmpeg.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals from .nodes import ( FilterNode, GlobalNode, diff --git a/ffmpeg/_filters.py b/ffmpeg/_filters.py index 9794e2c..6329648 100644 --- a/ffmpeg/_filters.py +++ b/ffmpeg/_filters.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals from .nodes import ( FilterNode, operator, diff --git a/ffmpeg/_run.py b/ffmpeg/_run.py index 28a3e46..d57b286 100644 --- a/ffmpeg/_run.py +++ b/ffmpeg/_run.py @@ -1,3 +1,6 @@ +from __future__ import unicode_literals + +from past.builtins import basestring import operator as _operator import subprocess as _subprocess @@ -13,6 +16,7 @@ from .nodes import ( operator, OutputNode, ) +from functools import reduce def _get_stream_name(name): return '[{}]'.format(name) diff --git a/ffmpeg/nodes.py b/ffmpeg/nodes.py index 61c9ff0..c6359e2 100644 --- a/ffmpeg/nodes.py +++ b/ffmpeg/nodes.py @@ -1,3 +1,6 @@ +from __future__ import unicode_literals + +from builtins import object import hashlib import json @@ -18,15 +21,18 @@ class Node(object): formatted_props += ['{}={!r}'.format(key, self._kwargs[key]) for key in sorted(self._kwargs)] return '{}({})'.format(self._name, ','.join(formatted_props)) + def __hash__(self): + return int(self._hash, base=16) + def __eq__(self, other): return self._hash == other._hash def _update_hash(self): props = {'args': self._args, 'kwargs': self._kwargs} - my_hash = hashlib.md5(json.dumps(props, sort_keys=True)).hexdigest() + my_hash = hashlib.md5(json.dumps(props, sort_keys=True).encode('utf-8')).hexdigest() parent_hashes = [parent._hash for parent in self._parents] hashes = parent_hashes + [my_hash] - self._hash = hashlib.md5(','.join(hashes)).hexdigest() + self._hash = hashlib.md5(','.join(hashes).encode('utf-8')).hexdigest() class InputNode(Node): diff --git a/ffmpeg/tests/test_ffmpeg.py b/ffmpeg/tests/test_ffmpeg.py index 7e38521..b8e983d 100644 --- a/ffmpeg/tests/test_ffmpeg.py +++ b/ffmpeg/tests/test_ffmpeg.py @@ -1,4 +1,4 @@ -from ffmpeg.nodes import operator, FilterNode +from __future__ import unicode_literals import ffmpeg import os import pytest @@ -72,12 +72,12 @@ def test_repr(): trim3 = ffmpeg.trim(in_file, start_frame=50, end_frame=60) concatted = ffmpeg.concat(trim1, trim2, trim3) output = ffmpeg.output(concatted, 'dummy2.mp4') - assert repr(in_file) == "input(filename='dummy.mp4')" + assert repr(in_file) == "input(filename={!r})".format('dummy.mp4') assert repr(trim1) == "trim(end_frame=20,start_frame=10)" assert repr(trim2) == "trim(end_frame=40,start_frame=30)" assert repr(trim3) == "trim(end_frame=60,start_frame=50)" assert repr(concatted) == "concat(n=3)" - assert repr(output) == "output(filename='dummy2.mp4')" + assert repr(output) == "output(filename={!r})".format('dummy2.mp4') def test_get_args_simple(): diff --git a/requirements.txt b/requirements.txt index 55ff9de..b5e8ae3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,5 @@ +future pytest +pytest-runner sphinx +tox diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..b7e4789 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[aliases] +test=pytest diff --git a/setup.py b/setup.py index d8b6334..0e11dab 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ -from distutils.core import setup -from ffmpeg._filters import __all__ as filter_names +from setuptools import setup from textwrap import dedent import subprocess @@ -61,18 +60,34 @@ misc_keywords = [ 'wrapper', ] -keywords = misc_keywords + file_formats + filter_names +keywords = misc_keywords + file_formats setup( - name = 'ffmpeg-python', - packages = ['ffmpeg'], - version = '0.1.5', - description = 'Python bindings for FFmpeg - with support for complex filtering', - author = 'Karl Kroening', - author_email = 'karlk@kralnet.us', - url = 'https://github.com/kkroening/ffmpeg-python', - download_url = download_url, - classifiers = [], - keywords = keywords, - long_description = long_description, + name='ffmpeg-python', + packages=['ffmpeg'], + setup_requires=['pytest-runner'], + tests_require=['pytest'], + version='0.1.5', + description='Python bindings for FFmpeg - with support for complex filtering', + author='Karl Kroening', + author_email='karlk@kralnet.us', + url='https://github.com/kkroening/ffmpeg-python', + download_url=download_url, + keywords=keywords, + long_description=long_description, + install_requires=['future'], + classifiers=[ + 'Intended Audience :: Developers', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + ], ) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..ed5c2e6 --- /dev/null +++ b/tox.ini @@ -0,0 +1,13 @@ +# Tox (https://tox.readthedocs.io/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py27, py33, py34, py35, py36, pypy + +[testenv] +commands = py.test +deps = + future + pytest