Create 2 pyi2ncommon rpms: for py3.3 and py3.6
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Wed, 5 Dec 2018 15:27:18 +0000 (16:27 +0100)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Wed, 5 Dec 2018 15:28:43 +0000 (16:28 +0100)
The python version, for which pyi2ncommon is installed on target machine,
is fixed in the rpm. It defaults to same version as build host. Managed
to change that by creating setup.cfg file dynamically while running
setup.py . With help of that script, can now create one version for
autotest (py3.6) and one for I2n systems (py3.3)

make_dist.py [new file with mode: 0755]
make_dist.sh [deleted file]

diff --git a/make_dist.py b/make_dist.py
new file mode 100755 (executable)
index 0000000..d5df1a2
--- /dev/null
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+
+"""
+Create rpm packages of pyi2ncommon for autotest (py3.6) and i2n system (py 3.3).
+
+Calls setup.py with different args. Add %check section to .spec file
+
+Accidentally stumbled of this: it appears that setting install-lib to
+/usr/lib/pythonVERSION/site-packages is translated by setup.py to installation
+requirement python(abi) = VERSION
+
+.. codeauthor:: Intra2net AG <info@intra2net.com>
+"""
+
+import os
+from os.path import join, isfile
+import sys
+from subprocess import call
+from tempfile import mkstemp
+from configparser import ConfigParser
+from glob import iglob
+
+INSTALL_DIR_PATTERN = '/usr/lib/python{}/site-packages'
+
+RPM_OPTIONS = dict(packager='Intra2net', group='Intra2net',
+                   vendor='Intra2net AG',
+                   requires='python3-zipfile35') \
+
+DIST_DIR = 'dist'
+SPEC_FILE = join(DIST_DIR, 'pyi2ncommon.spec')
+
+CFG_FILE = 'setup.cfg'
+
+SPEC_START = b"""
+# spec file created automatically by make_dist.sh -- do not modify!
+
+"""
+
+SPEC_CHECK_SECTION = b"""%check
+PYTHONPATH=./src:$PYTHONPATH && python3 -m unittest discover test
+
+"""
+
+def run_setup(command, cmd_line_args=None, install_options=None):
+    """
+    Run python3 setup.py with command and options.
+
+    Need this function since setup.py bdist_rpm does not accept --prefix and
+    --install-lib options. Need to write them into cfg file from which they
+    are then read ... Grrr!
+    """
+    config = ConfigParser()
+    if RPM_OPTIONS:
+        config['bdist_rpm'] = RPM_OPTIONS
+    if install_options:
+        config['install'] = install_options
+    need_delete = False
+    try:
+        with open(CFG_FILE, mode='xt') as write_handle:
+            need_delete = True
+            config.write(write_handle)
+        cmd = ['python3', 'setup.py', command]
+        if cmd_line_args:
+            cmd += cmd_line_args
+        if call(cmd) != 0:
+            raise RuntimeError('Running setup.py failed (cmd: {})'
+                               .format(' '.join(cmd)))
+    finally:
+        if need_delete:
+            os.unlink(CFG_FILE)
+            need_delete = False
+
+
+def create_rpm(py_version):
+    """Create rpm that will install pyi2ncommon for given python version."""
+    print('Creating RPM for python version {}'.format(py_version))
+
+    # define options for where to install library;
+    # It appears this is automatically translated into requirement
+    # python(abi) = version   !
+    install_options = {'prefix': '/'}
+    install_options['install-lib'] = INSTALL_DIR_PATTERN.format(py_version)
+
+    # create rpm
+    run_setup('bdist_rpm', install_options=install_options)
+
+    # find rpm and rename it
+    newest_name = None
+    newest_time = 0
+    for filename in iglob(join(DIST_DIR, 'pyi2ncommon-*.noarch.rpm')):
+        filetime = os.stat(filename).st_mtime
+        if filetime > newest_time:
+            newest_time = filetime
+            newest_name = filename
+
+    if newest_name is None:
+        raise RuntimeError('No pyi2ncommon rpm file found in {}'
+                           .format(DIST_DIR))
+    mod_name = newest_name[:-11] + '.py' + py_version.replace('.', '') + \
+               newest_name[-11:]
+    os.rename(newest_name, mod_name)
+    return mod_name
+
+
+def create_spec():
+    """Create .spec file and modify it."""
+    print('adapting spec file')
+    # create spec
+    run_setup('bdist_rpm', cmd_line_args=['--spec-only'])
+
+    # adapt
+    temp_handle = None
+    temp_name = None
+    try:
+        temp_handle, temp_file = mkstemp(dir=DIST_DIR, text=False,
+                                         prefix='pyi2ncommon-adapt-',
+                                         suffix='.spec')
+        os.write(temp_handle, SPEC_START)
+        did_write_check = False
+        with open(SPEC_FILE, 'rb') as reader:
+            for line in reader:
+                print('spec file: {}'.format(line.rstrip()))
+                if line.strip() == b'%install':
+                    os.write(temp_handle, SPEC_CHECK_SECTION)
+                    did_write_check = True
+                os.write(temp_handle, line)
+        os.close(temp_handle)
+        temp_handle = None
+
+        if not did_write_check:
+            raise RuntimeError('Could not find place to write %check section')
+
+        # replace
+        os.unlink(SPEC_FILE)
+        os.rename(temp_file, SPEC_FILE)
+        temp_file = None
+    finally:
+        # clean up temp
+        if temp_handle is not None:
+            os.close(temp_handle)
+        if temp_name is not None and isfile(temp_file):
+            os.unlink(temp_file)
+    return SPEC_FILE
+
+
+def main():
+    """
+    Main function, called when running file as script
+
+    see module doc for more info
+    """
+    for filename in (create_rpm('3.3'), create_rpm('3.6'), create_spec()):
+        print('Created {}'.format(filename))
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/make_dist.sh b/make_dist.sh
deleted file mode 100755 (executable)
index 5454c79..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/sh
-
-# The software in this package is distributed under the GNU General
-# Public License version 2 (with a special exception described below).
-#
-# A copy of GNU General Public License (GPL) is included in this distribution,
-# in the file COPYING.GPL.
-#
-# As a special exception, if other files instantiate templates or use macros
-# or inline functions from this file, or you compile this file and link it
-# with other works to produce a work based on this file, this file
-# does not by itself cause the resulting work to be covered
-# by the GNU General Public License.
-#
-# However the source code for this file must still be made available
-# in accordance with section (3) of the GNU General Public License.
-#
-# This exception does not invalidate any other reasons why a work based
-# on this file might be covered by the GNU General Public License.
-#
-# Copyright (c) 2016-2018 Intra2net AG <info@intra2net.com>
-
-echo create rpm
-python3 setup.py bdist_rpm --packager=Intra2net --group=Intra2net --vendor="Intra2net AG" --no-autoreq --requires="python3,python3-zipfile35"
-
-echo create spec
-python3 setup.py bdist_rpm --packager=Intra2net --group=Intra2net --vendor="Intra2net AG" --no-autoreq --requires="python3,python3-zipfile35" --spec-only
-
-echo adapt spec
-echo "# spec file created automatically by make_dist.sh -- do not modify!" > pyi2ncommon.spec
-echo "" >> ./pyi2ncommon.spec
-cat dist/pyi2ncommon.spec >> ./pyi2ncommon.spec
-echo "" >> ./pyi2ncommon.spec
-echo "%check" >> ./pyi2ncommon.spec
-#echo "echo \"unittests disabled for now...\"" >> ./pyi2ncommon.spec
-echo "PYTHONPATH=./src:\$PYTHONPATH && python3 -m unittest discover test" >> ./pyi2ncommon.spec
-mv ./pyi2ncommon.spec dist/