Merge ~jslarraz/review-tools:strip-pkg-functionality into review-tools:master

Proposed by Jorge Sancho Larraz
Status: Merged
Merged at revision: 80a9f97548e7365a60879e2a46940a6f85542941
Proposed branch: ~jslarraz/review-tools:strip-pkg-functionality
Merge into: review-tools:master
Diff against target: 220 lines (+46/-48)
4 files modified
reviewtools/common.py (+24/-35)
reviewtools/sr_common.py (+12/-3)
reviewtools/sr_lint.py (+1/-1)
reviewtools/sr_tests.py (+9/-9)
Reviewer Review Type Date Requested Status
Alex Murray Approve
Review via email: mp+466128@code.launchpad.net

Commit message

Strip snap related operations (unpack, extract file, list files, list binaries) from review class

Description of the change

Currently unpacking the snap, listing files and binaries and other operations are performed in the __init__function of the Review class. That means that those operations are repeated every time that the Review class or any of its subclasses (i.e. SnapReviewDeclaration, SnapReviewFunctional, SnapReviewLint, SnapReviewSecurity and potential future review classes) is instantiated.

This MR is intended to strip this functionality from the review class and define a self contained `container` class that handle this functionality. It will enable a followup MR where the `container` object is passed to review classes (instead of file name), thus removing the overhead caused by those duplicated operations.

Additionally pkg_filename, pkg_files and pkg_bin_files have been renamed to filename, files and bin_files as the pkg_prefix looks now redundant in the context of the `container`

To post a comment you must log in.
Revision history for this message
Alex Murray (alexmurray) wrote :

LGTM - just a couple minor things to update.

review: Needs Fixing
Revision history for this message
Jorge Sancho Larraz (jslarraz) wrote :
Revision history for this message
Alex Murray (alexmurray) wrote :

LGTM - thanks @jslarraz!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/reviewtools/common.py b/reviewtools/common.py
index 3e3ebdb..a61314a 100644
--- a/reviewtools/common.py
+++ b/reviewtools/common.py
@@ -296,8 +296,8 @@ class ReviewBase(object):
296 self.review_type = name296 self.review_type = name
297297
298298
299class Review(ReviewBase):299class BaseContainer:
300 """Common review class"""300 """Base container class"""
301301
302 magic_binary_file_descriptions = [302 magic_binary_file_descriptions = [
303 "application/x-executable; charset=binary",303 "application/x-executable; charset=binary",
@@ -310,37 +310,32 @@ class Review(ReviewBase):
310 "application/x-pie-executable",310 "application/x-pie-executable",
311 ]311 ]
312312
313 pkg_files = None313 files = None
314 pkg_bin_files = None314 bin_files = None
315
316 def __init__(self, fn, review_type, overrides=None):
317 ReviewBase.__init__(self, review_type, overrides)
318315
316 def __init__(self, fn):
319 self.tmp_dir = mkdtemp(prefix=MKDTEMP_PREFIX, dir=MKDTEMP_DIR)317 self.tmp_dir = mkdtemp(prefix=MKDTEMP_PREFIX, dir=MKDTEMP_DIR)
320 if os.path.isfile(fn):318 if os.path.isfile(fn):
321 if os.path.basename(fn).count(".") == 0:319 if os.path.basename(fn).count(".") == 0:
322 error("container filename must include an extension")320 error("container filename must include an extension")
323 self.pkg_filename = os.path.join(321 self.filename = os.path.join(
324 self.tmp_dir,322 self.tmp_dir,
325 os.path.basename(fn),323 os.path.basename(fn),
326 )324 )
327 shutil.copyfile(fn, self.pkg_filename)325 shutil.copyfile(fn, self.filename)
328 else:326 else:
329 error("Could not find '%s'" % fn)327 error("Could not find '%s'" % fn)
330328
331 self.unpack_dir = ".".join(self.pkg_filename.split(".")[:-1])329 self.unpack_dir = ".".join(self.filename.split(".")[:-1])
332 unpack_pkg(fn, dest=self.unpack_dir)330 unpack_pkg(fn, dest=self.unpack_dir)
333331
334 # unpack_pkg() now only supports snap v2, so just hardcode these
335 self.pkgfmt = {"type": "snap", "version": "16.04"}
336
337 # Get a list of all unpacked files332 # Get a list of all unpacked files
338 if self.pkg_files is None:333 if self.files is None:
339 self.pkg_files = self._list_all_files()334 self.files = self.get_files_list()
340335
341 # Setup what is needed to get a list of all unpacked compiled binaries336 # Setup what is needed to get a list of all unpacked compiled binaries
342 if self.pkg_bin_files is None:337 if self.bin_files is None:
343 self.pkg_bin_files = self._list_all_compiled_binaries()338 self.bin_files = self.get_compiled_binaries_list()
344339
345 def __del__(self):340 def __del__(self):
346 """341 """
@@ -360,26 +355,20 @@ class Review(ReviewBase):
360 error("Could not find '%s'" % rel)355 error("Could not find '%s'" % rel)
361 return open_file_read(fn)356 return open_file_read(fn)
362357
363 def _list_all_files(self):358 def get_files_list(self):
364 """List all files included in this package."""359 """List all files included in this package."""
365 pkg_files = []360 files = []
366 for root, dirnames, filenames in os.walk(self.unpack_dir):361 for root, dirnames, filenames in os.walk(self.unpack_dir):
367 for f in filenames:362 for f in filenames:
368 pkg_files.append(os.path.join(root, f))363 files.append(os.path.join(root, f))
369 return pkg_files364 return files
370
371 def _check_if_message_catalog(self, fn):
372 """Check if file is a message catalog (.mo file)."""
373 if fn.endswith(".mo"):
374 return True
375 return False
376365
377 def _list_all_compiled_binaries(self):366 def get_compiled_binaries_list(self):
378 """List all compiled binaries in this package."""367 """List all compiled binaries in this package."""
379 self.mime = magic.open(magic.MAGIC_MIME)368 self.mime = magic.open(magic.MAGIC_MIME)
380 self.mime.load()369 self.mime.load()
381 pkg_bin_files = []370 bin_files = []
382 for i in self.pkg_files:371 for i in self.files:
383 try:372 try:
384 res = self.mime.file(i)373 res = self.mime.file(i)
385 except Exception: # pragma: nocover374 except Exception: # pragma: nocover
@@ -389,12 +378,12 @@ class Review(ReviewBase):
389378
390 if (379 if (
391 res in self.magic_binary_file_descriptions380 res in self.magic_binary_file_descriptions
392 and not self._check_if_message_catalog(i)381 and not i.endswith(".mo") # check is not a message catalog
393 and i not in pkg_bin_files382 and i not in bin_files
394 ):383 ):
395 pkg_bin_files.append(i)384 bin_files.append(i)
396385
397 return pkg_bin_files386 return bin_files
398387
399388
400#389#
@@ -408,7 +397,7 @@ def error(out, exit_code=1, do_exit=True, output_type=None):
408 global RESULT_TYPES397 global RESULT_TYPES
409398
410 if output_type is not None:399 if output_type is not None:
411 Review.set_report_type(None, output_type)400 ReviewBase.set_report_type(None, output_type)
412401
413 try:402 try:
414 if REPORT_OUTPUT == "json":403 if REPORT_OUTPUT == "json":
diff --git a/reviewtools/sr_common.py b/reviewtools/sr_common.py
index fbd0472..adb0a86 100644
--- a/reviewtools/sr_common.py
+++ b/reviewtools/sr_common.py
@@ -21,8 +21,9 @@ import yaml
2121
2222
23from reviewtools.common import (23from reviewtools.common import (
24 Review,24 ReviewBase,
25 ReviewException,25 ReviewException,
26 BaseContainer,
26 error,27 error,
27 open_file_read,28 open_file_read,
28 read_snapd_base_declaration,29 read_snapd_base_declaration,
@@ -40,7 +41,7 @@ class SnapReviewException(ReviewException):
40 """This class represents SnapReview exceptions"""41 """This class represents SnapReview exceptions"""
4142
4243
43class SnapReview(Review):44class SnapReview(ReviewBase):
44 """This class represents snap reviews"""45 """This class represents snap reviews"""
4546
46 snappy_required = ["name", "version"]47 snappy_required = ["name", "version"]
@@ -414,7 +415,15 @@ class SnapReview(Review):
414 def __init__(self, fn, review_type, overrides=None):415 def __init__(self, fn, review_type, overrides=None):
415 if review_type is None: # for using utility functions416 if review_type is None: # for using utility functions
416 return417 return
417 Review.__init__(self, fn, review_type, overrides=overrides)418 ReviewBase.__init__(self, review_type, overrides=overrides)
419
420 self.snap = BaseContainer(fn)
421 # TODO: update code to directly use self.snap.xxx instead of assigning here
422 self.pkg_filename = self.snap.filename
423 self.unpack_dir = self.snap.unpack_dir
424 self.pkg_files = self.snap.files
425 self.pkg_bin_files = self.snap.bin_files
426 self.tmp_dir = self.snap.tmp_dir
418427
419 snap_yaml = self._extract_snap_yaml()428 snap_yaml = self._extract_snap_yaml()
420 try:429 try:
diff --git a/reviewtools/sr_lint.py b/reviewtools/sr_lint.py
index 3ddaf3f..095acf7 100644
--- a/reviewtools/sr_lint.py
+++ b/reviewtools/sr_lint.py
@@ -2008,7 +2008,7 @@ class SnapReviewLint(SnapReview):
2008 else:2008 else:
2009 appnames.append("%s.%s" % (self.snap_yaml["name"], app))2009 appnames.append("%s.%s" % (self.snap_yaml["name"], app))
20102010
2011 fh = self._extract_file(fn)2011 fh = self.snap._extract_file(fn)
2012 lines = fh.readlines()2012 lines = fh.readlines()
2013 fh.close()2013 fh.close()
20142014
diff --git a/reviewtools/sr_tests.py b/reviewtools/sr_tests.py
index 27b80ed..54c2a6f 100644
--- a/reviewtools/sr_tests.py
+++ b/reviewtools/sr_tests.py
@@ -22,7 +22,6 @@ import yaml
22from unittest.mock import patch22from unittest.mock import patch
23from unittest import TestCase23from unittest import TestCase
24from reviewtools.common import check_results as common_check_results24from reviewtools.common import check_results as common_check_results
25from reviewtools.common import ReviewBase
2625
27# These should be set in the test cases26# These should be set in the test cases
28TEST_SNAP_YAML = ""27TEST_SNAP_YAML = ""
@@ -43,13 +42,12 @@ def _mock_func(self):
43 return42 return
4443
4544
46class _Review:45class _BaseContainer:
47 def __init__(self, fn, review_type, overrides):46 def __init__(self, fn):
48 ReviewBase.__init__(self, review_type, overrides)47 self.filename = fn
49 self.pkg_filename = fn48 self.unpack_dir = ".".join(self.filename.split(".")[:-1])
50 self.unpack_dir = ".".join(self.pkg_filename.split(".")[:-1])49 self.files = []
51 self.pkg_files = []50 self.bin_files = []
52 self.pkg_bin_files = []
53 self.tmp_dir = "/faketmpdir"51 self.tmp_dir = "/faketmpdir"
5452
5553
@@ -88,7 +86,9 @@ def create_patches():
88 # Mock patching. Don't use decorators but instead patch in setUp() of the86 # Mock patching. Don't use decorators but instead patch in setUp() of the
89 # child.87 # child.
90 patches = []88 patches = []
91 patches.append(patch("reviewtools.sr_common.Review.__init__", _Review.__init__))89 patches.append(
90 patch("reviewtools.sr_common.BaseContainer.__init__", _BaseContainer.__init__)
91 )
92 patches.append(92 patches.append(
93 patch("reviewtools.sr_common.SnapReview._extract_snap_yaml", _extract_snap_yaml)93 patch("reviewtools.sr_common.SnapReview._extract_snap_yaml", _extract_snap_yaml)
94 )94 )

Subscribers

People subscribed via source and target branches