Permalink
Browse files

Add Python 3 support.

infoqscraper is now compatible with Python 2 and Python 3 (>= 2.6).
Comptability is ensured by the six module.

Currently only Python 2.7 and Python 3.3 have be tested. I plan to
use travis to run a wider test campaign.
  • Loading branch information...
1 parent a4dd74b commit 8e9086554a0c0b0f259b9df2e4f6fe712ccaa7ab @cykl committed Jan 4, 2014
View
@@ -12,7 +12,7 @@ the presenter but you don't get the slide.
* download the resources (video, audio track, slides)
* build a movie including the slides and the audio track from the resources
-Only Python 2.6 or later is currently supported.
+Python 2.6 or later are supported (including Python 3).
# Install
View
@@ -24,23 +24,10 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
-Portable shebang wrapper for Python 2.
-
-Some distro like Arch Linux link python to python3. Some other like Debian or
-OS X do not have a python2 symlink. It makes almost impossible to start a
-python2 using the shebang mechanism.
+Infoqscraper main wrapper
+"""
-This wrapper use the python symlink and its code is compatible with python2 and
-python3. If python3 is detected at runtime then it automaticaly switch to
-python2.
-"""
-import os
import sys
-
-if sys.version_info[0] != 2:
- sys.argv.insert(0, "python2")
- os.execl("/usr/bin/env", "/usr/bin/env", *sys.argv)
-
from infoqscraper import main
sys.exit(main.main())
@@ -21,15 +21,25 @@
# 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.
+
import os
+import subprocess
import sys
-import unittest2
-class TestInfoqscraper(unittest2.TestCase):
+from infoqscraper import utils
+
+from infoqscraper.test.compat import unittest
+
+
+class TestInfoqscraper(unittest.TestCase):
@property
def infoqscraper_path(self):
return os.path.join(os.path.dirname(__file__), "..", "..", "bin", "infoqscraper")
def build_cmd(self, args):
return [sys.executable, self.infoqscraper_path] + args
+
+ def run_cmd(self, args):
+ cmd = self.build_cmd(args)
+ return utils.check_output(cmd, stderr=subprocess.STDOUT).decode('utf-8')
@@ -21,30 +21,30 @@
# 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.
+
import subprocess
-import bintest
-from infoqscraper import utils
+from bintest.infoqscraper import TestInfoqscraper
usage_prefix = "usage: infoqscraper cache"
-class TestArguments(bintest.infoqscraper.TestInfoqscraper):
- def build_presentation_cmd(self, args):
- return self.build_cmd([]) + ['cache'] + args
+class TestArguments(TestInfoqscraper):
+
+ def setUp(self):
+ self.defaults_args = ["cache"]
def test_no_arg(self):
- cmd = self.build_presentation_cmd([])
+ pass
try:
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.defaults_args)
self.fail("Exception expected")
except subprocess.CalledProcessError as e:
self.assertEqual(e.returncode, 2)
- print e.output
- self.assertTrue(e.output.startswith(usage_prefix))
+ print(e.output)
+ self.assertTrue(e.output.decode('utf-8').startswith(usage_prefix))
def test_help(self):
- cmd = self.build_presentation_cmd(['--help'])
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ output = self.run_cmd(self.defaults_args + ["--help"])
self.assertTrue(output.startswith(usage_prefix))
@@ -21,53 +21,53 @@
# 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.
-import bintest
-from infoqscraper import client
-from infoqscraper import utils
import os
import shutil
import subprocess
import tempfile
+from infoqscraper import client
+from infoqscraper import utils
+
+from bintest.infoqscraper import TestInfoqscraper
+
usage_prefix = "usage: infoqscraper cache clear"
-class TestArguments(bintest.infoqscraper.TestInfoqscraper):
- def build_clear_cmd(self, args):
- return self.build_cmd([]) + ['cache', 'clear'] + args
+class TestArguments(TestInfoqscraper):
+
+ def setUp(self):
+ self.default_args = ['cache', 'clear']
def test_help(self):
- cmd = self.build_clear_cmd(['--help'])
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ output = self.run_cmd(self.default_args + ['--help'])
self.assertTrue(output.startswith(usage_prefix))
def test_clear(self):
# Ensure there is at least one file in the cache dir
infoq_client = client.InfoQ(cache_enabled=True)
- infoq_client.cache.put_content("testfile", "content")
+ infoq_client.cache.put_content("testfile", b"content")
# Backup the cache dir
backup_dir = infoq_client.cache.dir
tmp_dir = os.path.join(tempfile.mkdtemp(), os.path.basename(backup_dir))
shutil.copytree(backup_dir, tmp_dir)
try:
- cmd = self.build_clear_cmd([])
- utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_args)
self.assertFalse(os.path.exists(backup_dir))
# Now restore the cache dir
shutil.copytree(tmp_dir, backup_dir)
finally:
shutil.rmtree(os.path.dirname(tmp_dir))
def test_extra_arg(self):
- cmd = self.build_clear_cmd(["extra_args"])
try:
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_args + ['extra_args'])
self.fail("Exception expected")
except subprocess.CalledProcessError as e:
self.assertEqual(e.returncode, 2)
- print e.output
- self.assertTrue(e.output.startswith(usage_prefix))
+ print(e.output)
+ self.assertTrue(e.output.decode('utf8').startswith(usage_prefix))
@@ -21,38 +21,37 @@
# 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.
-import bintest
import subprocess
import re
from infoqscraper import utils
+from bintest.infoqscraper import TestInfoqscraper
+
usage_prefix = "usage: infoqscraper cache size"
-class TestArguments(bintest.infoqscraper.TestInfoqscraper):
- def build_size_cmd(self, args):
- return self.build_cmd([]) + ['cache', 'size'] + args
+class TestArguments(TestInfoqscraper):
+
+ def setUp(self):
+ self.default_cmd = ["cache", "size"]
def test_help(self):
- cmd = self.build_size_cmd(['--help'])
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ output = self.run_cmd(self.default_cmd + ["--help"])
self.assertTrue(output.startswith(usage_prefix))
def test_size(self):
# TODO: Find a better test
# We could use du -sh then compare its output to our.
- cmd = self.build_size_cmd([])
- output = utils.check_output(cmd, stderr=subprocess.STDOUT).strip()
+ output = self.run_cmd(self.default_cmd)
self.assertIsNotNone(re.match('\d{1,4}\.\d{2} \w{2,5}', output))
def test_extra_arg(self):
- cmd = self.build_size_cmd(["extra_args"])
try:
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_cmd + ["extra_args"])
self.fail("Exception expected")
except subprocess.CalledProcessError as e:
self.assertEqual(e.returncode, 2)
- print e.output
- self.assertTrue(e.output.startswith(usage_prefix))
+ print(e.output)
+ self.assertTrue(e.output.decode('utf8').startswith(usage_prefix))
@@ -21,72 +21,68 @@
# 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.
-import sys
-import bintest
+
import os
import shutil
import subprocess
+import sys
import tempfile
from infoqscraper import utils
+from bintest.infoqscraper import TestInfoqscraper
usage_prefix = "usage: infoqscraper presentation"
# Shorter is better to speed up the test suite.
short_presentation_id = "Batmanjs" # 25 minutes
-class TestArguments(bintest.infoqscraper.TestInfoqscraper):
- def build_download_cmd(self, args):
- return self.build_cmd([]) + ['-c', 'presentation', 'download'] + args
+class TestArguments(TestInfoqscraper):
+
+ def setUp(self):
+ self.default_cmd = ["-c", "presentation", "download"]
def test_help(self):
- cmd = self.build_download_cmd(['--help'])
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ output = self.run_cmd(self.default_cmd + ["--help"])
self.assertTrue(output.startswith(usage_prefix))
def test_no_arg(self):
- cmd = self.build_download_cmd([])
try:
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_cmd)
self.fail("Exception expected")
except subprocess.CalledProcessError as e:
self.assertEqual(e.returncode, 2)
- self.assertTrue(e.output.startswith(usage_prefix))
+ self.assertTrue(e.output.decode('utf8').startswith(usage_prefix))
def test_download_h264(self):
tmp_dir = tempfile.mkdtemp()
output_path = os.path.join(tmp_dir, "output.avi")
- cmd = self.build_download_cmd([short_presentation_id, '-o', output_path, '-t', 'h264'])
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_cmd + [short_presentation_id, "-o", output_path, "-t", "h264"])
self.assertTrue(os.path.exists(output_path))
shutil.rmtree(tmp_dir)
def test_download_h264_overlay(self):
tmp_dir = tempfile.mkdtemp()
output_path = os.path.join(tmp_dir, "output.avi")
- cmd = self.build_download_cmd([short_presentation_id, '-o', output_path, '-t', 'h264_overlay'])
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_cmd + [short_presentation_id, "-o", output_path, "-t", "h264_overlay"])
self.assertTrue(os.path.exists(output_path))
shutil.rmtree(tmp_dir)
def test_download_url(self):
tmp_dir = tempfile.mkdtemp()
output_path = os.path.join(tmp_dir, "output.avi")
url = "http://www.infoq.com/presentations/" + short_presentation_id
- cmd = self.build_download_cmd([url, '-o', output_path])
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_cmd + [url, "-o", output_path])
self.assertTrue(os.path.exists(output_path))
shutil.rmtree(tmp_dir)
def test_download_output_file_already_exist(self):
tmp_dir = tempfile.mkdtemp()
output_path = os.path.join(tmp_dir, "output.avi")
open(output_path, 'w').close()
- cmd = self.build_download_cmd([short_presentation_id, '-o', output_path])
with self.assertRaises(subprocess.CalledProcessError) as cm:
- utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_cmd + [short_presentation_id, "-o", output_path])
self.assertEquals(cm.exception.returncode, 1)
self.assertTrue(os.path.exists(output_path))
self.assertTrue(os.stat(output_path).st_size == 0)
@@ -96,29 +92,27 @@ def test_download_overwrite_output_file(self):
tmp_dir = tempfile.mkdtemp()
output_path = os.path.join(tmp_dir, "output.avi")
open(output_path, 'w').close()
- cmd = self.build_download_cmd([short_presentation_id, '-o', output_path, '-y'])
- utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_cmd + [short_presentation_id, "-o", output_path, "-y"])
self.assertTrue(os.path.exists(output_path))
self.assertTrue(os.stat(output_path).st_size > 0)
shutil.rmtree(tmp_dir)
def assert_bad_command(self, args):
- cmd = self.build_download_cmd(args)
try:
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_cmd + args)
self.fail("Exception expected")
except subprocess.CalledProcessError as e:
self.assertEqual(e.returncode, 2)
- self.assertTrue(e.output.startswith(usage_prefix))
+ self.assertTrue(e.output.decode('utf8').startswith(usage_prefix))
def test_bad_ffmpeg(self):
- self.assert_bad_command(['--ffmpeg', "/bad/ffmpeg/path"])
+ self.assert_bad_command(["--ffmpeg", "/bad/ffmpeg/path"])
def test_bad_swfrender(self):
- self.assert_bad_command(['--swfrender', "/bad/swfrender/path"])
+ self.assert_bad_command(["--swfrender", "/bad/swfrender/path"])
def test_bad_rtmpdump(self):
- self.assert_bad_command(['--rtmpdump', "/bad/rtmpdump/path"])
+ self.assert_bad_command(["--rtmpdump", "/bad/rtmpdump/path"])
def test_custom_ffmpeg(self):
if sys.platform.startswith("win32"):
@@ -129,12 +123,11 @@ def test_custom_ffmpeg(self):
tmp_dir = tempfile.mkdtemp()
try:
alias_path = os.path.join(tmp_dir, "ffmpeg")
- print ffmpeg_path
+ print(ffmpeg_path)
os.symlink(ffmpeg_path, alias_path)
output_path = os.path.join(tmp_dir, "output.avi")
- cmd = self.build_download_cmd([short_presentation_id, '-o', output_path])
- output = utils.check_output(cmd, stderr=subprocess.STDOUT)
+ self.run_cmd(self.default_cmd + [short_presentation_id, "-o", output_path])
self.assertTrue(os.path.exists(output_path))
finally:
shutil.rmtree(tmp_dir)
Oops, something went wrong.

0 comments on commit 8e90865

Please sign in to comment.