def eggify(self): '''Let's wrap a nice Python module into an ugly egg.''' j = os.path.join # First, clean the Python module cleanFolder(self.pythonModule, verbose=False) # Create the egg folder eggFullName = j(self.eggFolder, self.eggName) if os.path.exists(eggFullName): os.remove(eggFullName) print('Existing "%s" was removed.' % eggFullName) # Create a temp folder where to store the egg eggTempFolder = os.path.splitext(eggFullName)[0] if os.path.exists(eggTempFolder): FolderDeleter.delete(eggTempFolder) print('Removed "%s" that was in my way.' % eggTempFolder) os.mkdir(eggTempFolder) # Create the "Products" sub-folder if we must wrap the package in this # namespace eggModulePath = j(j(eggTempFolder, self.moduleName.replace('.', '/'))) # Copy the Python module into the egg. os.makedirs(eggModulePath) copyFolder(self.pythonModule, eggModulePath) # Create setup files in the root egg folder self.createSetupFile(eggTempFolder) self.createInitFile(eggTempFolder) self.zipResult(eggFullName, eggTempFolder)
def eggify(self): '''Let's wrap a nice Python module into an ugly egg.''' j = os.path.join # First, clean the Python module cleanFolder(self.pythonModule, verbose=False) # Create the egg folder eggFullName = j(self.eggFolder, self.eggName) if os.path.exists(eggFullName): os.remove(eggFullName) print 'Existing "%s" was removed.' % eggFullName # Create a temp folder where to store the egg eggTempFolder = os.path.splitext(eggFullName)[0] if os.path.exists(eggTempFolder): FolderDeleter.delete(eggTempFolder) print 'Removed "%s" that was in my way.' % eggTempFolder os.mkdir(eggTempFolder) # Create the "Products" sub-folder if we must wrap the package in this # namespace eggModulePath = j(j(eggTempFolder, self.moduleName.replace('.', '/'))) # Copy the Python module into the egg. os.makedirs(eggModulePath) copyFolder(self.pythonModule, eggModulePath) # Create setup files in the root egg folder self.createSetupFile(eggTempFolder) self.createInitFile(eggTempFolder) self.zipResult(eggFullName, eggTempFolder)
def run(self, verbose=True): cleanFolder(appyPath, verbose=verbose) # Remove all files in temp folders for tempFolder in ('%s/temp' % appyPath, '%s/pod/test/temp' % appyPath): if os.path.exists(tempFolder): FolderDeleter.delete(tempFolder) # Remove test reports if any for testReport in ('%s/pod/test/Tester.report.txt' % appyPath,): if os.path.exists(testReport): os.remove(testReport)
def run(self, verbose=True): cleanFolder(appyPath, verbose=verbose) # Remove all files in temp folders for tempFolder in ('%s/temp' % appyPath, '%s/pod/test/temp' % appyPath): if os.path.exists(tempFolder): FolderDeleter.delete(tempFolder) # Remove test reports if any for testReport in ('%s/pod/test/Tester.report.txt' % appyPath, ): if os.path.exists(testReport): os.remove(testReport)
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) destFolder = j(libFolder, self.appName) shutil.copytree(self.app, destFolder) # Clean dest folder (.svn/.bzr files) cleanFolder(destFolder, folders=('.svn', '.bzr')) # When packaging Appy itself, everything is in /usr/lib/pythonX. When # packaging an Appy app, we will generate more files for creating a # running instance. if self.appName != 'appy': # Create the folders that will collectively represent the deployed # Zope instance. binFolder = j(debFolder, 'usr', 'bin') os.makedirs(binFolder) # <app>ctl name = '%s/%sctl' % (binFolder, self.appNameLower) f = file(name, 'w') f.write(appCtl % self.appNameLower) os.chmod(name, 0744) # Make it executable by owner. f.close() # <app>run name = '%s/%srun' % (binFolder, self.appNameLower) f = file(name, 'w') f.write(appRun % self.appNameLower) os.chmod(name, 0744) # Make it executable by owner. f.close() # startlo name = '%s/startlo' % binFolder f = file(name, 'w') f.write(loStart) f.close() os.chmod(name, 0744) # Make it executable by owner. # /var/lib/<app> (will store Data.fs, lock files, etc) varLibFolder = j(debFolder, 'var', 'lib', self.appNameLower) os.makedirs(varLibFolder) f = file('%s/README' % varLibFolder, 'w') f.write('This folder stores the %s database.\n' % self.appName) f.close() # /var/log/<app> (will store event.log and Z2.log) varLogFolder = j(debFolder, 'var', 'log', self.appNameLower) os.makedirs(varLogFolder) f = file('%s/README' % varLogFolder, 'w') f.write('This folder stores the log files for %s.\n' % self.appName) f.close() # /etc/<app>.conf (Zope configuration file) etcFolder = j(debFolder, 'etc') os.makedirs(etcFolder) name = '%s/%s.conf' % (etcFolder, self.appNameLower) n = self.appNameLower f = file(name, 'w') productsFolder = '/usr/lib/python%s/%s/zope' % \ (self.pythonVersions[0], self.appName) f.write(zopeConf % ('/var/lib/%s' % n, '/var/lib/%s' % n, '/var/log/%s' % n, str(self.zopePort), 'products %s\n' % productsFolder)) f.close() # /etc/init.d/<app> (start the app at boot time) initdFolder = j(etcFolder, 'init.d') os.makedirs(initdFolder) name = '%s/%s' % (initdFolder, self.appNameLower) f = file(name, 'w') n = self.appNameLower f.write(initScript % (n, n, 'Start Zope with the Appy-based %s ' \ 'application.' % n, '%sctl start' % n, '%sctl restart' % n, '%sctl stop' % n)) f.close() os.chmod(name, 0744) # Make it executable by owner # /etc/init.d/lo (start LibreOffice at boot time) name = '%s/lo' % initdFolder f = file(name, 'w') f.write(initScript % ('lo','lo', 'Start LibreOffice in server mode', 'startlo', 'startlo', "#Can't stop LO.")) f.write('\n') f.close() os.chmod(name, 0744) # Make it executable by owner. # Get the size of the app, in Kb. os.chdir(tempFolder) out, err = executeCommand(['du', '-b', '-s', 'debian']) size = int(int(out.split()[0])/1024.0) os.chdir(debFolder) # Create data.tar.gz based on it executeCommand(['tar', 'czvf', 'data.tar.gz', '*']) # Create the control file f = file('control', 'w') nameSuffix = '' dependencies = [] if self.appName != 'appy': nameSuffix = '-%s' % self.appNameLower 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], depends)) f.close() # Create md5sum file f = file('md5sums', 'w') toWalk = ['usr'] if self.appName != 'appy': toWalk += ['etc', 'var'] for folderToWalk in toWalk: for dir, dirnames, filenames in os.walk(folderToWalk): 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 # - change ownership of some files if required # - [in the case of an app-package] call update-rc.d for starting it at # boot time. 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) content += 'if [ -e %s ]\nthen\n%sfi\n' % (bin, cmds) if self.appName != 'appy': # Allow user "zope", that runs the Zope instance, to write the # database and log files. content += 'chown -R zope:root /var/lib/%s\n' % self.appNameLower content += 'chown -R zope:root /var/log/%s\n' % self.appNameLower # Call update-rc.d for starting the app at boot time content += 'update-rc.d %s defaults\n' % self.appNameLower content += 'update-rc.d lo defaults\n' # (re-)start the app content += '%sctl restart\n' % self.appNameLower # (re-)start lo content += 'startlo\n' 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 executeCommand(['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 signature if required if self.sign: # Create the concatenated version of all files within the deb out, err = executeCommand(['cat', 'debian-binary', 'control.tar.gz', 'data.tar.gz']) f = file('/tmp/combined-contents', 'wb') f.write(out) f.close() executeCommand(['gpg', '-abs', '-o', '_gpgorigin', '/tmp/combined-contents']) signFile = '_gpgorigin' os.remove('/tmp/combined-contents') # Export the public key and name it according to its ID as found by # analyzing the result of command "gpg --fingerprint". out, err = executeCommand(['gpg', '--fingerprint']) fingerprint = out.split('\n') id = 'pubkey' for line in fingerprint: if '=' not in line: continue id = line.split('=')[1].strip() id = ''.join(id.split()[-4:]) break out, err = executeCommand(['gpg', '--export', '-a']) f = file('%s/%s.asc' % (self.out, id), 'w') f.write(out) f.close() else: signFile = None # Create the .deb package debName = 'python-appy%s-%s.deb' % (nameSuffix, self.appVersion) cmd = ['ar', '-r', debName] if signFile: cmd.append(signFile) cmd += ['debian-binary', 'control.tar.gz', 'data.tar.gz'] out, err = executeCommand(cmd) # Move it to self.out os.rename(j(debFolder, debName), j(self.out, debName)) # Clean temp files FolderDeleter.delete(debFolder) os.chdir(curdir)
def createInstance(self, linksForProducts): '''Calls the Zope script that allows to create a Zope instance and copy into it all the Plone packages and products.''' j = os.path.join # Find the Python interpreter running Zope for elem in os.listdir(self.plonePath): pythonPath = None elemPath = j(self.plonePath, elem) if elem.startswith('Python-') and os.path.isdir(elemPath): pythonPath = elemPath + '/bin/python' if not os.path.exists(pythonPath): raise NewError(PYTHON_EXE_NOT_FOUND % pythonPath) break if not pythonPath: raise NewError(PYTHON_NOT_FOUND % self.plonePath) self.pythonPath = pythonPath # Find the Zope script mkzopeinstance.py and Zope itself makeInstancePath = None self.zopePath = None for dirname, dirs, files in os.walk(self.plonePath): # Find Zope for folderName in dirs: if folderName.startswith('Zope2-'): self.zopePath = j(dirname, folderName) # Find mkzopeinstance for fileName in files: if fileName == 'mkzopeinstance.py': if self.ploneVersion == 'plone4': makeInstancePath = j(dirname, fileName) else: if ('/buildout-cache/' not in dirname): makeInstancePath = j(dirname, fileName) if not makeInstancePath: raise NewError(MKZOPE_NOT_FOUND % self.plonePath) # Execute mkzopeinstance.py with the right Python interpreter. # For Plone4, we will call it later. cmd = [pythonPath, makeInstancePath, '-d', self.instancePath] if self.ploneVersion != 'plone4': print(cmd) executeCommand(cmd) # Now, make the instance Plone-ready action = 'Copying' if linksForProducts: action = 'Symlinking' print('%s Plone stuff in the Zope instance...' % action) if self.ploneVersion in ('plone25', 'plone30'): self.installPlone25or30Stuff(linksForProducts) elif self.ploneVersion in ('plone3x', 'plone4'): versions = self.copyEggs() if self.ploneVersion == 'plone3x': self.patchPlone3x() elif self.ploneVersion == 'plone4': # Create the Zope instance os.environ['PYTHONPATH'] = '%s:%s' % \ (j(self.instancePath,'Products'), j(self.instancePath, 'lib/python')) print(cmd) executeCommand(cmd) self.patchPlone4(versions) # Remove .bat files under Linux if os.name == 'posix': cleanFolder(j(self.instancePath, 'bin'), exts=('.bat',))
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) destFolder = j(libFolder, self.appName) shutil.copytree(self.app, destFolder) # Clean dest folder (.svn/.bzr files) cleanFolder(destFolder, folders=('.svn', '.bzr')) # When packaging Appy itself, everything is in /usr/lib/pythonX. When # packaging an Appy app, we will generate more files for creating a # running instance. if self.appName != 'appy': # Create the folders that will collectively represent the deployed # Zope instance. binFolder = j(debFolder, 'usr', 'bin') os.makedirs(binFolder) # <app>ctl name = '%s/%sctl' % (binFolder, self.appNameLower) f = file(name, 'w') f.write(appCtl % self.appNameLower) os.chmod(name, 0744) # Make it executable by owner. f.close() # <app>run name = '%s/%srun' % (binFolder, self.appNameLower) f = file(name, 'w') f.write(appRun % self.appNameLower) os.chmod(name, 0744) # Make it executable by owner. f.close() # startoo name = '%s/startoo' % binFolder f = file(name, 'w') f.write(ooStart) f.close() os.chmod(name, 0744) # Make it executable by owner. # /var/lib/<app> (will store Data.fs, lock files, etc) varLibFolder = j(debFolder, 'var', 'lib', self.appNameLower) os.makedirs(varLibFolder) f = file('%s/README' % varLibFolder, 'w') f.write('This folder stores the %s database.\n' % self.appName) f.close() # /var/log/<app> (will store event.log and Z2.log) varLogFolder = j(debFolder, 'var', 'log', self.appNameLower) os.makedirs(varLogFolder) f = file('%s/README' % varLogFolder, 'w') f.write('This folder stores the log files for %s.\n' % self.appName) f.close() # /etc/<app>.conf (Zope configuration file) etcFolder = j(debFolder, 'etc') os.makedirs(etcFolder) name = '%s/%s.conf' % (etcFolder, self.appNameLower) n = self.appNameLower f = file(name, 'w') productsFolder = '/usr/lib/python%s/%s/zope' % \ (self.pythonVersions[0], self.appName) f.write(zopeConf % ('/var/lib/%s' % n, '/var/lib/%s' % n, '/var/log/%s' % n, str(self.zopePort), 'products %s\n' % productsFolder)) f.close() # /etc/init.d/<app> (start the app at boot time) initdFolder = j(etcFolder, 'init.d') os.makedirs(initdFolder) name = '%s/%s' % (initdFolder, self.appNameLower) f = file(name, 'w') n = self.appNameLower f.write(initScript % (n, n, 'Start Zope with the Appy-based %s ' \ 'application.' % n, '%sctl start' % n, '%sctl restart' % n, '%sctl stop' % n)) f.close() os.chmod(name, 0744) # Make it executable by owner. # /etc/init.d/oo (start OpenOffice at boot time) name = '%s/oo' % initdFolder f = file(name, 'w') f.write(initScript % ('oo', 'oo', 'Start OpenOffice in server mode', 'startoo', 'startoo', "#Can't stop OO.")) f.write('\n') f.close() os.chmod(name, 0744) # Make it executable by owner. # Get the size of the app, in Kb. os.chdir(tempFolder) cmd = subprocess.Popen(['du', '-b', '-s', 'debian'], stdout=subprocess.PIPE) size = int(int(cmd.stdout.read().split()[0]) / 1024.0) os.chdir(debFolder) # Create data.tar.gz based on it. os.system('tar czvf data.tar.gz *') # Create the control file f = file('control', 'w') nameSuffix = '' dependencies = [] if self.appName != 'appy': nameSuffix = '-%s' % self.appNameLower 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], depends)) f.close() # Create md5sum file f = file('md5sums', 'w') toWalk = ['usr'] if self.appName != 'appy': toWalk += ['etc', 'var'] for folderToWalk in toWalk: for dir, dirnames, filenames in os.walk(folderToWalk): 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 # - change ownership of some files if required # - [in the case of an app-package] call update-rc.d for starting it at # boot time. 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) content += 'if [ -e %s ]\nthen\n%sfi\n' % (bin, cmds) if self.appName != 'appy': # Allow user "zope", that runs the Zope instance, to write the # database and log files. content += 'chown -R zope:root /var/lib/%s\n' % self.appNameLower content += 'chown -R zope:root /var/log/%s\n' % self.appNameLower # Call update-rc.d for starting the app at boot time content += 'update-rc.d %s defaults\n' % self.appNameLower content += 'update-rc.d oo defaults\n' # (re-)start the app content += '%sctl restart\n' % self.appNameLower # (re-)start oo content += 'startoo\n' 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 signature if required if self.sign: # Create the concatenated version of all files within the deb os.system('cat debian-binary control.tar.gz data.tar.gz > ' \ '/tmp/combined-contents') os.system('gpg -abs -o _gpgorigin /tmp/combined-contents') signFile = '_gpgorigin ' os.remove('/tmp/combined-contents') # Export the public key and name it according to its ID as found by # analyzing the result of command "gpg --fingerprint". cmd = subprocess.Popen(['gpg', '--fingerprint'], stdout=subprocess.PIPE) fingerprint = cmd.stdout.read().split('\n') id = 'pubkey' for line in fingerprint: if '=' not in line: continue id = line.split('=')[1].strip() id = ''.join(id.split()[-4:]) break os.system('gpg --export -a > %s/%s.asc' % (self.out, id)) else: signFile = '' # Create the .deb package debName = 'python-appy%s-%s.deb' % (nameSuffix, self.appVersion) os.system('ar -r %s %sdebian-binary control.tar.gz data.tar.gz' % \ (debName, signFile)) # Move it to self.out os.rename(j(debFolder, debName), j(self.out, debName)) # Clean temp files FolderDeleter.delete(debFolder) os.chdir(curdir)
def createInstance(self, linksForProducts): '''Calls the Zope script that allows to create a Zope instance and copy into it all the Plone packages and products.''' j = os.path.join # Find the Python interpreter running Zope for elem in os.listdir(self.plonePath): pythonPath = None elemPath = j(self.plonePath, elem) if elem.startswith('Python-') and os.path.isdir(elemPath): pythonPath = elemPath + '/bin/python' if not os.path.exists(pythonPath): raise NewError(PYTHON_EXE_NOT_FOUND % pythonPath) break if not pythonPath: raise NewError(PYTHON_NOT_FOUND % self.plonePath) self.pythonPath = pythonPath # Find the Zope script mkzopeinstance.py and Zope itself makeInstancePath = None self.zopePath = None for dirname, dirs, files in os.walk(self.plonePath): # Find Zope for folderName in dirs: if folderName.startswith('Zope2-'): self.zopePath = j(dirname, folderName) # Find mkzopeinstance for fileName in files: if fileName == 'mkzopeinstance.py': if self.ploneVersion == 'plone4': makeInstancePath = j(dirname, fileName) else: if ('/buildout-cache/' not in dirname): makeInstancePath = j(dirname, fileName) if not makeInstancePath: raise NewError(MKZOPE_NOT_FOUND % self.plonePath) # Execute mkzopeinstance.py with the right Python interpreter. # For Plone4, we will call it later. cmd = '%s %s -d %s' % (pythonPath, makeInstancePath, self.instancePath) if self.ploneVersion != 'plone4': print cmd os.system(cmd) # Now, make the instance Plone-ready action = 'Copying' if linksForProducts: action = 'Symlinking' print '%s Plone stuff in the Zope instance...' % action if self.ploneVersion in ('plone25', 'plone30'): self.installPlone25or30Stuff(linksForProducts) elif self.ploneVersion in ('plone3x', 'plone4'): versions = self.copyEggs() if self.ploneVersion == 'plone3x': self.patchPlone3x() elif self.ploneVersion == 'plone4': # Create the Zope instance os.environ['PYTHONPATH'] = '%s:%s' % \ (j(self.instancePath,'Products'), j(self.instancePath, 'lib/python')) print cmd os.system(cmd) self.patchPlone4(versions) # Remove .bat files under Linux if os.name == 'posix': cleanFolder(j(self.instancePath, 'bin'), exts=('.bat',))