[PATCH 08/14] Move Anaconda version detection from isys to Python code
Martin Kolman
mkolman at redhat.com
Thu Aug 21 20:10:29 UTC 2014
There is now pyanaconda/version.py.in module with a __version__
variable, which automatically gets the Anaconda version from
automake during build and is saved as pyanaconda/version.py.
As a side effect, the absence of compiled isys no longer crashes
"anaconda --help". Also "anaconda --version" on freshly
cloned/unpackaged Anaconda now correctly returns "anaconda unknown".
Also handle issues with auto* and version.py. Automake is really kind of
terrible at python, so filter the generated version.py out of the dist
files so that builds from a dist tarball don't end up with a both a $srcdir
and $builddir copy of version.py. Ignore a pylint error about importing version
since version.py ends up in a different directory than the rest of the
pyanaconda module.
Related: rhbz:#1088459
Signed-off-by: Martin Kolman <mkolman at redhat.com>
---
.gitignore | 1 +
anaconda | 18 +++++-----
configure.ac | 1 +
pyanaconda/Makefile.am | 6 +++-
pyanaconda/exception.py | 4 +--
pyanaconda/isys/Makefile.am | 3 +-
pyanaconda/isys/__init__.py | 4 +--
pyanaconda/isys/isys.c | 6 ----
pyanaconda/startup_utils.py | 80 +++++++++++++++++++++++++++++++++++++++++++++
pyanaconda/version.py.in | 1 +
10 files changed, 102 insertions(+), 22 deletions(-)
create mode 100644 pyanaconda/startup_utils.py
create mode 100644 pyanaconda/version.py.in
diff --git a/.gitignore b/.gitignore
index d50106c..3ba6538 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,3 +80,4 @@ widgets/gtk-doc.make
widgets/src/gettext.h
anaconda.po
data/liveinst/gnome/fedora-welcome.po
+pyanaconda/version.py
diff --git a/anaconda b/anaconda
index c91ae6b..d33d712 100755
--- a/anaconda
+++ b/anaconda
@@ -205,11 +205,13 @@ def symlink_updates(dest_dir, update_dir):
continue
os.symlink(dest_path, update_path)
-def getAnacondaVersion():
- # Using _isys here so we don't drag in the logging stuff, which is always
- # complicated.
- from pyanaconda import _isys
- return _isys.getAnacondaVersion()
+def getAnacondaVersionString():
+ # we are importing the startup module directly so that it can be replaced
+ # by updates image, if it was replaced before the updates image can be
+ # loaded, it could not be easily replaced
+ from pyanaconda import startup_utils
+ return startup_utils.get_anaconda_version_string()
+
def parseArguments(argv=None, boot_cmdline=None):
from pyanaconda.anaconda_argparse import AnacondaArgumentParser
@@ -233,7 +235,7 @@ def parseArguments(argv=None, boot_cmdline=None):
# If this seems like too much trouble, *don't add a new option*!
# Version
- ap.add_argument('--version', action='version', version="%(prog)s " + getAnacondaVersion())
+ ap.add_argument('--version', action='version', version="%(prog)s " + getAnacondaVersionString())
# Interface
ap.add_argument("-C", "--cmdline", dest="display_mode", action="store_const", const="c",
@@ -760,7 +762,7 @@ if __name__ == "__main__":
if "RUNKS" in flags.cmdline:
opts.display_mode = 'c'
- log.info("%s %s", sys.argv[0], getAnacondaVersion())
+ log.info("%s %s", sys.argv[0], getAnacondaVersionString())
# TODO: uncomment this when we're sure that we're doing the right thing
# with flags.cmdline *everywhere* it appears...
@@ -786,7 +788,7 @@ if __name__ == "__main__":
from pyanaconda import keyboard
from pyanaconda.iutil import ProxyString, ProxyStringError
- verdesc = "%s for %s %s" % (getAnacondaVersion(),
+ verdesc = "%s for %s %s" % (getAnacondaVersionString(),
product.productName, product.productVersion)
if product.isFinal:
print "anaconda %s started." % verdesc
diff --git a/configure.ac b/configure.ac
index 08e6e75..d8853f3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -236,6 +236,7 @@ AC_CONFIG_FILES([Makefile
po/Makefile.in
scripts/Makefile
pyanaconda/Makefile
+ pyanaconda/version.py
pyanaconda/isys/Makefile
pyanaconda/packaging/Makefile
pyanaconda/ui/Makefile
diff --git a/pyanaconda/Makefile.am b/pyanaconda/Makefile.am
index ae1159c..2d48bd2 100644
--- a/pyanaconda/Makefile.am
+++ b/pyanaconda/Makefile.am
@@ -24,4 +24,8 @@ MAINTAINERCLEANFILES = Makefile.in
# anaconda Python code
pkgpyexecdir = $(pyexecdir)/py$(PACKAGE_NAME)
anacondadir = $(pkgpyexecdir)
-anaconda_PYTHON = $(srcdir)/*.py
+
+# Filter version.py out of the distributed python files since it will
+# be generated by the configure script
+anaconda_PYTHON = $(filter-out %/version.py,$(wildcard $(srcdir)/*.py))
+nodist_anaconda_PYTHON = $(builddir)/version.py
diff --git a/pyanaconda/exception.py b/pyanaconda/exception.py
index 7a8941e..3ec6ebf 100644
--- a/pyanaconda/exception.py
+++ b/pyanaconda/exception.py
@@ -24,7 +24,6 @@
from meh import Config
from meh.handler import ExceptionHandler
from meh.dump import ReverseExceptionDump
-from pyanaconda import isys
from pyanaconda import iutil
import sys
import os
@@ -40,6 +39,7 @@ from pyanaconda.threads import threadMgr
from pyanaconda.i18n import _
from pyanaconda import flags
from pyanaconda import product
+from pyanaconda import startup_utils
from gi.repository import GLib
@@ -225,7 +225,7 @@ def initExceptionHandling(anaconda):
fileList.extend([anaconda.opts.ksfile])
conf = Config(programName="anaconda",
- programVersion=isys.getAnacondaVersion(),
+ programVersion=startup_utils.get_anaconda_version_string(),
programArch=os.uname()[4],
attrSkipList=["_intf._actions",
"_intf._currentAction._xklwrapper",
diff --git a/pyanaconda/isys/Makefile.am b/pyanaconda/isys/Makefile.am
index 3f37d45..5b24cf7 100644
--- a/pyanaconda/isys/Makefile.am
+++ b/pyanaconda/isys/Makefile.am
@@ -23,8 +23,7 @@ ISYS_SRCS = isofs.c linkdetect.c auditd.c log.c mem.c
dist_noinst_HEADERS = $(srcdir)/*.h
-ISYS_CFLAGS = -DVERSION='"$(PACKAGE_VERSION)-$(PACKAGE_RELEASE)"' \
- $(NETWORKMANAGER_CFLAGS) $(LIBNL_CFLAGS) $(LIBNM_GLIB_CFLAGS) \
+ISYS_CFLAGS = $(NETWORKMANAGER_CFLAGS) $(LIBNL_CFLAGS) $(LIBNM_GLIB_CFLAGS) \
$(SELINUX_CFLAGS)
ISYS_LIBS = $(RESOLV_LIBS) $(ZLIB_LIBS) \
$(DEVMAPPER_LIBS) $(X11_LIBS) $(SELINUX_LIBS) \
diff --git a/pyanaconda/isys/__init__.py b/pyanaconda/isys/__init__.py
index 91bc505..30e8517 100755
--- a/pyanaconda/isys/__init__.py
+++ b/pyanaconda/isys/__init__.py
@@ -1,7 +1,7 @@
#
# isys.py - installer utility functions and glue for C module
#
-# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
+# Copyright (C) 2001-2014 Red Hat, Inc.
# All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
@@ -108,8 +108,6 @@ def isPaeAvailable():
return isPAE
-def getAnacondaVersion():
- return _isys.getAnacondaVersion()
auditDaemon = _isys.auditdaemon
diff --git a/pyanaconda/isys/isys.c b/pyanaconda/isys/isys.c
index 7848504..d166738 100644
--- a/pyanaconda/isys/isys.c
+++ b/pyanaconda/isys/isys.c
@@ -80,7 +80,6 @@ static PyObject * py_bind_textdomain_codeset(PyObject * o, PyObject * args);
static PyObject * doSegvHandler(PyObject *s, PyObject *args);
static PyObject * doAuditDaemon(PyObject *s);
static PyObject * doIsCapsLockEnabled(PyObject * s, PyObject * args);
-static PyObject * doGetAnacondaVersion(PyObject * s, PyObject * args);
static PyObject * doInitLog(PyObject * s);
static PyObject * doTotalMemory(PyObject * s);
@@ -94,7 +93,6 @@ static PyMethodDef isysModuleMethods[] = {
{ "handleSegv", (PyCFunction) doSegvHandler, METH_VARARGS, NULL },
{ "auditdaemon", (PyCFunction) doAuditDaemon, METH_NOARGS, NULL },
{ "isCapsLockEnabled", (PyCFunction) doIsCapsLockEnabled, METH_VARARGS, NULL },
- { "getAnacondaVersion", (PyCFunction) doGetAnacondaVersion, METH_VARARGS, NULL },
{ "initLog", (PyCFunction) doInitLog, METH_VARARGS, NULL },
{ "total_memory", (PyCFunction) doTotalMemory, METH_NOARGS, NULL },
{ NULL, NULL, 0, NULL }
@@ -250,10 +248,6 @@ static PyObject * doIsCapsLockEnabled(PyObject * s, PyObject * args) {
return PyBool_FromLong(state.locked_mods & LockMask);
}
-static PyObject * doGetAnacondaVersion(PyObject * s, PyObject * args) {
- return Py_BuildValue("s", VERSION);
-}
-
static PyObject * doInitLog(PyObject * s) {
openLog();
Py_INCREF(Py_None);
diff --git a/pyanaconda/startup_utils.py b/pyanaconda/startup_utils.py
new file mode 100644
index 0000000..30d5974
--- /dev/null
+++ b/pyanaconda/startup_utils.py
@@ -0,0 +1,80 @@
+#
+# startup.py - code used during early startup with minimal dependencies
+#
+# Copyright (C) 2014 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties 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., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Martin Kolman <mkolman at redhat.com>
+#
+import imp
+
+
+def module_exists(module_path):
+ """Report is a given module exists in the current module import pth or not.
+ Supports checking bot modules ("foo") os submodules ("foo.bar.baz")
+
+ :param str module_path: (sub)module identifier
+
+ :returns: True if (sub)module exists in path, False if not
+ :rtype: bool
+ """
+
+ module_path_components = module_path.split(".")
+ module_name = module_path_components.pop()
+ parent_module_path = None
+ if module_path_components:
+ # the path specifies a submodule ("bar.foo")
+ # we need to chain-import all the modules in the submodule path before
+ # we can check if the submodule itself exists
+ for name in module_path_components:
+ module_info = imp.find_module(name, parent_module_path)
+ module = imp.load_module(name, *module_info)
+ if module:
+ parent_module_path = module.__path__
+ else:
+ # one of the parents was not found, abort search
+ return False
+ # if we got this far we should have either some path or the module is
+ # not a submodule and the default set of paths will be used (path=None)
+ try:
+ # if the module is not found imp raises an ImportError
+ imp.find_module(module_name, parent_module_path)
+ return True
+ except ImportError:
+ return False
+
+
+def get_anaconda_version_string():
+ """Return a string describing current Anaconda version.
+ If the current version can't be determined the string
+ "unknown" will be returned.
+
+ :returns: string describing Anaconda version
+ :rtype: str
+ """
+
+ # we are importing the version module directly so that we don't drag in any
+ # non-necessary stuff; we also need to handle the possibility of the
+ # import itself failing
+ if module_exists("pyanaconda.version"):
+ # Ignore pylint not finding the version module, since thanks to automake
+ # there's a good chance that version.py is not in the same directory as
+ # the rest of pyanaconda.
+ from pyanaconda import version # pylint: disable=no-name-in-module
+ return version.__version__
+ else:
+ return "unknown"
+
diff --git a/pyanaconda/version.py.in b/pyanaconda/version.py.in
new file mode 100644
index 0000000..8b5161a
--- /dev/null
+++ b/pyanaconda/version.py.in
@@ -0,0 +1 @@
+__version__ = "@PACKAGE_VERSION at -@PACKAGE_RELEASE@"
--
1.9.3
More information about the anaconda-patches
mailing list