[arch-projects] [namcap][PATCH] Add setuptools rule

Felix Yan felixonmars at gmail.com
Fri Feb 21 06:10:27 EST 2014


This rule detects python imports from pkg_resources from
python*-setupsools in /usr/bin/*. Missing dependency on corresponding
setuptools package will render the executables unusable.

Signed-off-by: Felix Yan <felixonmars at gmail.com>
---
 Namcap/rules/__init__.py                |  1 +
 Namcap/rules/setuptools.py              | 73 +++++++++++++++++++++++++++++++++
 Namcap/tests/package/test_setuptools.py | 71 ++++++++++++++++++++++++++++++++
 namcap-tags                             |  2 +
 4 files changed, 147 insertions(+)
 create mode 100644 Namcap/rules/setuptools.py
 create mode 100644 Namcap/tests/package/test_setuptools.py

diff --git a/Namcap/rules/__init__.py b/Namcap/rules/__init__.py
index f7780d2..d42a241 100644
--- a/Namcap/rules/__init__.py
+++ b/Namcap/rules/__init__.py
@@ -44,6 +44,7 @@ from . import (
   permissions,
   rpath,
   scrollkeeper,
+  setuptools,
   shebangdepends,
   sodepends,
   symlink
diff --git a/Namcap/rules/setuptools.py b/Namcap/rules/setuptools.py
new file mode 100644
index 0000000..1b1a3b4
--- /dev/null
+++ b/Namcap/rules/setuptools.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+#
+# namcap rules - setuptools
+# Copyright (C) 2014 Felix Yan <felixonmars at gmail.com>
+# 
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+# 
+
+from Namcap.ruleclass import *
+import Namcap.depends
+
+def check_setuptools(pyfile):
+    "returns python prefix if need setuptools, else False"
+    try:
+        shebang = pyfile.readline().decode("utf8")
+    except UnicodeDecodeError:
+        # Not a text file
+        return False
+
+    if "python" in shebang:
+        try:
+            rest_of_file = "\n" + pyfile.read().decode("utf8")
+        except UnicodeDecodeError:
+            return False
+
+        # Simple test
+        if "\nfrom pkg_resources import" in rest_of_file or "\nimport pkg_resources" in rest_of_file:
+            return "python2" if "python2" in shebang else "python"
+
+    return False
+
+class package(TarballRule):
+    name = "setuptools"
+    description = "Checks that Python executables under /usr/bin that uses pkg_resources have setuptools as a dependency"
+    def analyze(self, pkginfo, tar):
+        executables = [ f for f in tar
+            if f.name.startswith("usr/bin") and f.isfile() ]
+        if len(executables) == 0:
+            return
+
+        # If there are executables, check for pkg_resources reference
+
+        need_setuptools = []
+        for executable in executables:
+            pyfile = tar.extractfile(executable)
+
+            if pyfile is None:
+                continue
+
+            python_prefix = check_setuptools(pyfile)
+            if python_prefix:
+                need_setuptools.append(executable.name)
+
+        if len(need_setuptools):
+            potential_depends = (python_prefix + "-setuptools", python_prefix + "-distribute")
+            if not any(dependency in pkginfo.get("depends") or dependency in Namcap.depends.getcovered(pkginfo.get("depends")) for dependency in potential_depends):
+                self.infos.append(("setuptools-needed-dep %s in %s", (python_prefix + "-setuptools", need_setuptools)))
+                reasons = pkginfo.detected_deps.setdefault(python_prefix + "-setuptools", [])
+                reasons.append( ('setuptools-needed %s', str(need_setuptools)) )
+
+# vim: set ts=4 sw=4 noet:
diff --git a/Namcap/tests/package/test_setuptools.py b/Namcap/tests/package/test_setuptools.py
new file mode 100644
index 0000000..1593604
--- /dev/null
+++ b/Namcap/tests/package/test_setuptools.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+#
+# namcap tests - setuptools
+# Copyright (C) 2014 Felix Yan <felixonmars at gmail.com>
+# 
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+#   USA
+# 
+
+import os
+
+from Namcap.tests.makepkg import MakepkgTest
+import Namcap.rules.setuptools
+
+class SetuptoolsProgramsTest(MakepkgTest):
+    pkgbuild = """
+pkgname=__namcap_test_setuptools
+pkgver=1.0
+pkgrel=1
+pkgdesc="A Good Python2 package"
+arch=('any')
+url="http://www.example.com/"
+license=('GPL')
+depends=('python2')
+options=(!purge !zipman)
+source=()
+build() {
+  true
+}
+package() {
+  mkdir -p "${pkgdir}/usr/bin"
+  tee "${pkgdir}/usr/bin/foobar" << EOF
+#!/usr/bin/python2
+from pkg_resources import load_entry_point
+EOF
+}
+"""
+
+    def test_setuptools_files(self):
+        pkgfile = "__namcap_test_setuptools-1.0-1-any.pkg.tar"
+        with open(os.path.join(self.tmpdir, "PKGBUILD"), "w") as f:
+            f.write(self.pkgbuild)
+        self.run_makepkg()
+        pkg, r = self.run_rule_on_tarball(
+            os.path.join(self.tmpdir, pkgfile),
+            Namcap.rules.setuptools.package
+        )
+        e, w, i = Namcap.depends.analyze_depends(pkg)
+        self.assertEqual(e + r.errors,
+                [('dependency-detected-not-included %s (%s)',
+                  ('python2-setuptools', "needed for programs ['usr/bin/foobar']")
+                 )])
+        self.assertEqual(r.warnings, [])
+        self.assertTrue(
+            ("setuptools-needed-dep %s in %s", ("python2-setuptools", ["usr/bin/foobar"]))
+            in r.infos)
+
+
+# vim: set ts=4 sw=4 noet:
diff --git a/namcap-tags b/namcap-tags
index d638478..fa23abe 100644
--- a/namcap-tags
+++ b/namcap-tags
@@ -69,6 +69,7 @@ potential-non-fhs-info-page %s :: Potential non-FHS info page (%s) found.
 potential-non-fhs-man-page %s :: Potential non-FHS man page (%s) found.
 script-link-detected %s in %s :: Script link detected (%s) in file %s
 scrollkeeper-dir-exists %s :: Scrollkeeper directory exists (%s). Remember to not run scrollkeeper till post_{install,upgrade,remove}.
+setuptools-needed-dep %s in %s :: %s probably needed for python programs %s to run correctly
 site-ruby :: Found usr/lib/ruby/site_ruby in package, usr/lib/ruby/vendor_ruby should be used instead.
 specific-host-type-used %s :: Reference to %s should be changed to $CARCH
 specific-sourceforge-mirror :: Attempting to use specific sourceforge mirror, use downloads.sourceforge.net instead
@@ -98,3 +99,4 @@ kdebase-runtime-needed %s :: needed for programs %s
 java-environment-needed %s :: found class files %s
 libraries-needed %s %s :: libraries %s needed in files %s
 programs-needed %s %s :: programs %s needed in scripts %s
+setuptools-needed %s :: needed for programs %s
-- 
1.9.0



More information about the arch-projects mailing list