Add possibility to load package from open zip file

Currently ZipLoader can take only path to zip file with package,
but murano-python client sometimes use path a container for file
content. This behavior should be supported by validator too.

* Increased coverage for ZipLoader
* Fixed minor bug with file list

Change-Id: Ied8b332b7890134e176169c56edf6ba8a5fa1645
This commit is contained in:
sslypushenko 2016-09-20 16:06:52 +03:00
parent c0dbd9fc2e
commit 9dcc3296ba
2 changed files with 65 additions and 3 deletions

View File

@ -150,7 +150,10 @@ class ZipLoader(BaseLoader):
def __init__(self, path):
super(ZipLoader, self).__init__(path)
self._zipfile = zipfile.ZipFile(self.path)
if hasattr(self.path, 'read'):
self._zipfile = zipfile.ZipFile(six.BytesIO(self.path.read()))
else:
self._zipfile = zipfile.ZipFile(self.path)
@classmethod
def _try_load(cls, path):
@ -163,11 +166,12 @@ class ZipLoader(BaseLoader):
return self._zipfile.open(name, mode)
def list_files(self, subdir=None):
files = self._zipfile.namelist()
files = [file_ for file_ in self._zipfile.namelist()
if not file_.endswith('/')]
if subdir is None:
return files
subdir_len = len(subdir)
return [file_[subdir_len:].lstrip('/') for file_ in files
return [file_[subdir_len:].strip('/') for file_ in files
if file_.startswith(subdir)]
def exists(self, name):

View File

@ -13,7 +13,9 @@
# under the License.
import mock
import zipfile
import six
import yaml
import yaml.error
@ -184,3 +186,59 @@ class DirectoryLoaderTest(base.TestCase):
self.assertTrue(pkg.exists('1.yaml'))
m_exists.return_value = False
self.assertFalse(pkg.exists('1.yaml'))
class ZipLoaderTest(base.TestCase):
@mock.patch.object(pkg_loader.ZipLoader, 'read')
@mock.patch.object(pkg_loader.ZipLoader, 'try_set_format')
@mock.patch.object(pkg_loader.ZipLoader, 'exists')
@mock.patch('muranopkgcheck.pkg_loader.zipfile')
def _load_fake_pkg(self, m_zip, m_exists, m_try_set_format, m_read):
m_zip_file = m_zip.ZipFile.return_value
m_read.return_value.yaml.return_value = [{'FullName': 'fake'}]
m_exists.return_value = True
loader = pkg_loader.ZipLoader.try_load('fake')
m_try_set_format.assert_called_once_with({'FullName': 'fake'})
m_zip.ZipFile.assert_called_once_with('fake')
return loader, m_zip_file
def test_try_load(self):
pkg, _ = self._load_fake_pkg()
self.assertEqual('fake', pkg.path)
with mock.patch('muranopkgcheck.pkg_loader.zipfile.ZipFile') as m_zip:
m_zip.side_effect = zipfile.BadZipfile
pkg = pkg_loader.ZipLoader.try_load('fake')
self.assertEqual(None, pkg)
@mock.patch.object(pkg_loader.ZipLoader, 'read')
@mock.patch.object(pkg_loader.ZipLoader, 'try_set_format')
@mock.patch.object(pkg_loader.ZipLoader, 'exists')
@mock.patch('muranopkgcheck.pkg_loader.zipfile')
def test_try_load_from_bytesio(self, m_zip, m_exists, m_try_set_format,
m_read):
m_read.return_value.yaml.return_value = [{'FullName': 'fake'}]
m_exists.return_value = True
m_content = str('fake') if six.PY2 else bytes('fake', 'latin-1')
loader = pkg_loader.ZipLoader.try_load(six.BytesIO(m_content))
self.assertIsNotNone(loader)
m_try_set_format.assert_called_once_with({'FullName': 'fake'})
m_zip.ZipFile.assert_called()
def test_list_files(self):
pkg, m_zip = self._load_fake_pkg()
m_zip.namelist.return_value = ['1', '2', 'sub/', 'sub/3', 'sub/4']
self.assertEqual(['1', '2', 'sub/3', 'sub/4'],
pkg.list_files())
self.assertEqual(['3', '4'],
pkg.list_files(subdir='sub'))
def test_exist(self):
pkg, m_zip = self._load_fake_pkg()
self.assertTrue(pkg.exists('1.yaml'))
m_zip.getinfo.side_effect = KeyError
self.assertFalse(pkg.exists('1.yaml'))
m_zip.getinfo.side_effect = [KeyError, None]
self.assertTrue(pkg.exists('sub'))
m_zip.getinfo.side_effect = [KeyError, KeyError]
self.assertFalse(pkg.exists('sub'))