diff --git a/.gitignore b/.gitignore index 2aa1b18..3f03a81 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ *.pyc +.cache/ +.coverage +adb.egg-info/ +.tox/ /adb.zip /fastboot.zip diff --git a/.travis.yml b/.travis.yml index c6ac7d5..2de6a3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: python sudo: false python: - - 2.7 + - 3.6 addons: apt: @@ -21,6 +21,7 @@ install: - pip install tox coveralls env: + - TOXENV=py36 - TOXENV=py27 script: tox diff --git a/README.md b/README.md index 896bfe2..f35545c 100644 --- a/README.md +++ b/README.md @@ -78,4 +78,4 @@ for i in xrange(10): [coverage_link]: https://coveralls.io/github/google/python-adb?branch=master [build_img]: https://travis-ci.org/google/python-adb.svg?branch=master [build_link]: https://travis-ci.org/google/python-adb -[pycon_preso]: https://docs.google.com/a/google.com/presentation/d/e/2PACX-1vQ6DsSqOZ3oJBPM72OfxAz7FIxZ0f6tM8ZvAjp15ck9xr5cbtFBgshgOdlIAMmCoO8XmGVOc_c4iWqR/pub?start=false&loop=false&delayms=15000 +[pycon_preso]: https://docs.google.com/presentation/d/1bv8pmm8TZp4aFxoq2ohA-ms_a3BWci7D3tYvVGIm8T0/pub?start=false&loop=false&delayms=10000 diff --git a/adb/adb_commands.py b/adb/adb_commands.py index b37cae4..c4820f0 100644 --- a/adb/adb_commands.py +++ b/adb/adb_commands.py @@ -22,7 +22,7 @@ All timeouts are in milliseconds. """ -import cStringIO +import io import os import socket @@ -142,7 +142,7 @@ def Push(self, source_file, device_filename, mtime='0', timeout_ms=None): mtime: Optional, modification time to set on the file. timeout_ms: Expected timeout for any part of the push. """ - if isinstance(source_file, basestring): + if isinstance(source_file, str): if os.path.isdir(source_file): self.Shell("mkdir " + device_filename) for f in os.listdir(source_file): @@ -168,8 +168,8 @@ def Pull(self, device_filename, dest_file='', timeout_ms=None): The file data if dest_file is not set. """ if not dest_file: - dest_file = cStringIO.StringIO() - elif isinstance(dest_file, basestring): + dest_file = io.StringIO() + elif isinstance(dest_file, str): dest_file = open(dest_file, 'w') connection = self.protocol_handler.Open( self.handle, destination='sync:', @@ -178,7 +178,7 @@ def Pull(self, device_filename, dest_file='', timeout_ms=None): connection.Close() # An empty call to cStringIO.StringIO returns an instance of # cStringIO.OutputType. - if isinstance(dest_file, cStringIO.OutputType): + if isinstance(dest_file, io.StringIO): return dest_file.getvalue() def Stat(self, device_filename): diff --git a/adb/adb_protocol.py b/adb/adb_protocol.py index d118528..a3c800a 100644 --- a/adb/adb_protocol.py +++ b/adb/adb_protocol.py @@ -184,6 +184,8 @@ def checksum(self): @staticmethod def CalculateChecksum(data): # The checksum is just a sum of all the bytes. I swear. + if isinstance(data, bytes): + return sum(map(ord, data.decode('ascii'))) & 0xFFFFFFFF return sum(map(ord, data)) & 0xFFFFFFFF def Pack(self): @@ -229,7 +231,11 @@ def Read(cls, usb, expected_cmds, timeout_ms=None, total_timeout_ms=None): data = '' while data_length > 0: temp = usb.BulkRead(data_length, timeout_ms) - data += temp + if isinstance(temp, bytes): + data += temp.decode('ascii') + else: + data += temp + data_length -= len(temp) actual_checksum = cls.CalculateChecksum(data) diff --git a/adb/fastboot.py b/adb/fastboot.py index 177a916..26958eb 100644 --- a/adb/fastboot.py +++ b/adb/fastboot.py @@ -16,10 +16,16 @@ import argparse import binascii import collections -import cStringIO import logging import os import struct +import sys + +PYTHON_27 = sys.version_info < (3,0) +if PYTHON_27: + from cStringIO import StringIO +else: + from io import StringIO from adb import common from adb import usb_exceptions @@ -87,7 +93,8 @@ def SendCommand(self, command, arg=None): """ if arg is not None: command = '%s:%s' % (command, arg) - self._Write(cStringIO.StringIO(command), len(command)) + + self._Write(StringIO(command), len(command)) def HandleSimpleResponses( self, timeout_ms=None, info_cb=DEFAULT_MESSAGE_CALLBACK): @@ -189,7 +196,7 @@ def _Write(self, data, length, progress_callback=None): """Sends the data to the device, tracking progress with the callback.""" if progress_callback: progress = self._HandleProgress(length, progress_callback) - progress.next() + next(progress) while length: tmp = data.read(self.chunk_kb * 1024) length -= len(tmp) @@ -277,14 +284,14 @@ def Download(self, source_file, source_len=0, Returns: Response to a download request, normally nothing. """ - if isinstance(source_file, basestring): + if isinstance(source_file, str): source_len = os.stat(source_file).st_size source_file = open(source_file) if source_len == 0: # Fall back to storing it all in memory :( data = source_file.read() - source_file = cStringIO.StringIO(data) + source_file = StringIO(data) source_len = len(data) self._protocol.SendCommand('download', '%08x' % source_len) diff --git a/adb/filesync_protocol.py b/adb/filesync_protocol.py index 2d4e776..d0db429 100644 --- a/adb/filesync_protocol.py +++ b/adb/filesync_protocol.py @@ -135,12 +135,12 @@ def __init__(self, adb_connection, recv_header_format): self.adb = adb_connection # Sending - self.send_buffer = '' + self.send_buffer = b'' self.send_header_len = struct.calcsize('<2I') # Receiving self.recv_buffer = '' - self.recv_header_format = recv_header_format + self.recv_header_format = recv_header_format.encode('utf8') self.recv_header_len = struct.calcsize(recv_header_format) def Send(self, command_id, data='', size=0): @@ -158,10 +158,9 @@ def Send(self, command_id, data='', size=0): size = len(data) if not self._CanAddToSendBuffer(len(data)): - self._Flush() - + self._Flush() header = struct.pack('<2I', self.id_to_wire[command_id], size) - self.send_buffer += header + data + self.send_buffer += header + data.encode('utf8') def Read(self, expected_ids, read_data=True): """Read ADB messages and return FileSync packets.""" @@ -169,7 +168,7 @@ def Read(self, expected_ids, read_data=True): self._Flush() # Read one filesync packet off the recv buffer. - header_data = self._ReadBuffered(self.recv_header_len) + header_data = self._ReadBuffered(self.recv_header_len).encode('utf8') header = struct.unpack(self.recv_header_format, header_data) # Header is (ID, ...). command_id = self.wire_to_id[header[0]] diff --git a/setup.py b/setup.py index 37d00c0..664c58d 100644 --- a/setup.py +++ b/setup.py @@ -54,7 +54,8 @@ 'Development Status :: 4 - Beta', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python', - #'Programming Language :: Python :: 3', ## import cStringIO fails with python3 + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3', 'Topic :: Software Development :: Testing' ] ) diff --git a/test/adb_test.py b/test/adb_test.py index 6b89782..26fbf62 100755 --- a/test/adb_test.py +++ b/test/adb_test.py @@ -14,7 +14,7 @@ # limitations under the License. """Tests for adb.""" -import cStringIO +import io import struct import unittest @@ -159,7 +159,7 @@ def _MakeSyncHeader(cls, command, *int_parts): @classmethod def _MakeWriteSyncPacket(cls, command, data='', size=None): - return cls._MakeSyncHeader(command, size or len(data)) + data + return cls._MakeSyncHeader(command, size or len(data)) + data.encode("ascii") @classmethod def _ExpectSyncCommand(cls, write_commands, read_commands): @@ -180,7 +180,7 @@ def _ExpectSyncCommand(cls, write_commands, read_commands): return usb def testPush(self): - filedata = 'alo there, govnah' + filedata = u'alo there, govnah' mtime = 100 send = [ @@ -189,10 +189,10 @@ def testPush(self): self._MakeWriteSyncPacket('DONE', size=mtime), ] data = 'OKAY\0\0\0\0' - usb = self._ExpectSyncCommand([''.join(send)], [data]) + usb = self._ExpectSyncCommand([b''.join(send)], [data]) adb_commands = self._Connect(usb) - adb_commands.Push(cStringIO.StringIO(filedata), '/data', mtime=mtime) + adb_commands.Push(io.StringIO(filedata), '/data', mtime=mtime) def testPull(self): filedata = "g'ddayta, govnah" @@ -202,7 +202,7 @@ def testPull(self): self._MakeWriteSyncPacket('DATA', filedata), self._MakeWriteSyncPacket('DONE'), ] - usb = self._ExpectSyncCommand([recv], [''.join(data)]) + usb = self._ExpectSyncCommand([recv], [b''.join(data)]) adb_commands = self._Connect(usb) self.assertEqual(filedata, adb_commands.Pull('/data')) diff --git a/test/common_stub.py b/test/common_stub.py index 0e3c911..a248a89 100644 --- a/test/common_stub.py +++ b/test/common_stub.py @@ -20,9 +20,11 @@ def __init__(self): def BulkWrite(self, data, unused_timeout_ms=None): expected_data = self.written_data.pop(0) + if type(expected_data) != type(data) and isinstance(expected_data, bytes): + expected_data = expected_data.decode('utf8') if expected_data != data: - raise ValueError('Expected %s, got %s (%s)' % ( - _Dotify(expected_data), binascii.hexlify(data), _Dotify(data))) + raise ValueError('Expected %s got %s (%s)' % ( + _Dotify(expected_data), binascii.hexlify(data), _Dotify(data))) def BulkRead(self, length, timeout_ms=None): # pylint: disable=unused-argument diff --git a/test/fastboot_test.py b/test/fastboot_test.py index 983691b..42f269c 100755 --- a/test/fastboot_test.py +++ b/test/fastboot_test.py @@ -14,7 +14,13 @@ # limitations under the License. """Tests for adb.fastboot.""" -import cStringIO +import sys +PYTHON_27 = sys.version_info < (3,0) + +if PYTHON_27: + from cStringIO import StringIO +else: + from io import StringIO import os import tempfile import unittest @@ -58,7 +64,7 @@ def ExpectFlash(self, partition, succeed=True): def testDownload(self): raw = 'aoeuidhtnsqjkxbmwpyfgcrl' - data = cStringIO.StringIO(raw) + data = StringIO(raw) self.ExpectDownload([raw]) commands = fastboot.FastbootCommands(self.usb) @@ -68,14 +74,14 @@ def testDownload(self): def testDownloadFail(self): raw = 'aoeuidhtnsqjkxbmwpyfgcrl' - data = cStringIO.StringIO(raw) + data = StringIO(raw) self.ExpectDownload([raw], succeed=False) commands = fastboot.FastbootCommands(self.usb) with self.assertRaises(fastboot.FastbootRemoteFailure): commands.Download(data) - data = cStringIO.StringIO(raw) + data = StringIO(raw) self.ExpectDownload([raw], accept_data=False) with self.assertRaises(fastboot.FastbootTransferError): commands.Download(data) @@ -86,7 +92,7 @@ def testFlash(self): self.ExpectFlash(partition) commands = fastboot.FastbootCommands(self.usb) - output = cStringIO.StringIO() + output = StringIO() def InfoCb(message): if message.header == 'INFO': output.write(message.message) @@ -108,7 +114,7 @@ def testFlashFromFile(self): # More than one packet, ends somewhere into the 3rd packet. raw = 'SOMETHING' * 1086 tmp = tempfile.NamedTemporaryFile(delete=False) - tmp.write(raw) + tmp.write(raw.encode('ascii')) tmp.close() progresses = [] diff --git a/tox.ini b/tox.ini index aa9670d..4880a55 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ [tox] envlist = + py36 py27 [testenv]