# ------------------------------------------------------------------------------ import os, os.path, subprocess, md5, shutil from appy.shared.utils import getOsTempFolder, FolderDeleter # ------------------------------------------------------------------------------ debianInfo = '''Package: python-appy%s Version: %s Architecture: all Maintainer: Gaetan Delannay Installed-Size: %d Depends: python (>= %s), python (<= %s)%s Section: python Priority: optional Homepage: http://appyframework.org Description: Appy builds simple but complex web Python apps. ''' class Debianizer: '''This class allows to produce a Debian package from a Python (Appy) package.''' def __init__(self, app, out, appVersion='0.1.0', pythonVersions=('2.6', '2.7'), depends=('zope2.12', 'openoffice.org', 'imagemagick')): # app is the path to the Python package to Debianize. self.app = app self.appName = os.path.basename(app) # out is the folder where the Debian package will be generated. self.out = out # What is the version number for this app ? self.appVersion = appVersion # On which Python versions will the Debian package depend? self.pythonVersions = pythonVersions # Debian package dependencies self.depends = depends def run(self): '''Generates the Debian package.''' curdir = os.getcwd() j = os.path.join tempFolder = getOsTempFolder() # Create, in the temp folder, the required sub-structure for the Debian # package. debFolder = j(tempFolder, 'debian') if os.path.exists(debFolder): FolderDeleter.delete(debFolder) # Copy the Python package into it srcFolder = j(debFolder, 'usr', 'lib') for version in self.pythonVersions: libFolder = j(srcFolder, 'python%s' % version) os.makedirs(libFolder) shutil.copytree(self.app, j(libFolder, self.appName)) # Create data.tar.gz based on it. os.chdir(debFolder) os.system('tar czvf data.tar.gz ./usr') # Get the size of the app, in Kb. cmd = subprocess.Popen(['du', '-b', '-s', 'usr'],stdout=subprocess.PIPE) size = int(int(cmd.stdout.read().split()[0])/1024.0) # Create the control file f = file('control', 'w') nameSuffix = '' dependencies = [] if self.appName != 'appy': nameSuffix = '-%s' % self.appName.lower() dependencies.append('python-appy') if self.depends: for d in self.depends: dependencies.append(d) depends = '' if dependencies: depends = ', ' + ', '.join(dependencies) f.write(debianInfo % (nameSuffix, self.appVersion, size, self.pythonVersions[0], self.pythonVersions[1], depends)) f.close() # Create md5sum file f = file('md5sums', 'w') for dir, dirnames, filenames in os.walk('usr'): for name in filenames: m = md5.new() pathName = j(dir, name) currentFile = file(pathName, 'rb') while True: data = currentFile.read(8096) if not data: break m.update(data) currentFile.close() # Add the md5 sum to the file f.write('%s %s\n' % (m.hexdigest(), pathName)) f.close() # Create postinst, a script that will: # - bytecompile Python files after the Debian install # - create a Zope instance (excepted if we are installing Appy itself). f = file('postinst', 'w') content = '#!/bin/sh\nset -e\n' for version in self.pythonVersions: bin = '/usr/bin/python%s' % version lib = '/usr/lib/python%s' % version cmds = ' %s -m compileall -q %s/%s 2> /dev/null\n' % (bin, lib, self.appName) if self.appName != 'appy': inst = '/home/zope/%sInstance' % self.appName cmds += ' if [ -e %s ]\n then\n' % inst # If the Zope instance already exists, simply restart it. cmds += ' %s/bin/zopectl restart\n else\n' % inst # Else, create a Zope instance in the home of user "zope". cmds += ' %s %s/appy/bin/new.py zope /usr/lib/zope2.12 ' \ '%s\n' % (bin, lib, inst) # Within this instance, create a symlink to the Zope product cmds += ' ln -s %s/%s/zope %s/Products/%s\n' % \ (lib, self.appName, inst, self.appName) # Launch the instance cmds += ' %s/bin/zopectl start\n' % inst # Launch OpenOffice in server mode cmds += ' %s/bin/startoo\n fi\n' % inst content += 'if [ -e %s ]\nthen\n%sfi\n' % (bin, cmds) f.write(content) f.close() # Create prerm, a script that will remove all pyc files before removing # the Debian package. f = file('prerm', 'w') content = '#!/bin/sh\nset -e\n' for version in self.pythonVersions: content += 'find /usr/lib/python%s/%s -name "*.pyc" -delete\n' % \ (version, self.appName) f.write(content) f.close() # Create control.tar.gz os.system('tar czvf control.tar.gz ./control ./md5sums ./postinst ' \ './prerm') # Create debian-binary f = file('debian-binary', 'w') f.write('2.0\n') f.close() # Create the .deb package debName = 'python-appy%s-%s.deb' % (nameSuffix, self.appVersion) os.system('ar -r %s debian-binary control.tar.gz data.tar.gz' % \ debName) # Move it to self.out os.rename(j(debFolder, debName), j(self.out, debName)) # Clean temp files FolderDeleter.delete(debFolder) os.chdir(curdir) # ------------------------------------------------------------------------------