appy.bin: generate.py: one less arg: outputFolder has been removed (the script now generates the Zope product in <appFolder>/zope); generate.py: new option '-d', for generating a Debian package from the Python (Appy) app.
This commit is contained in:
parent
a89d65afc6
commit
13443ea79e
5 changed files with 171 additions and 121 deletions
119
shared/packaging.py
Normal file
119
shared/packaging.py
Normal file
|
@ -0,0 +1,119 @@
|
|||
# ------------------------------------------------------------------------------
|
||||
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 <gaetan.delannay@geezteem.com>
|
||||
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')):
|
||||
# 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
|
||||
|
||||
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 = ''
|
||||
depends = ''
|
||||
if self.appName != 'appy':
|
||||
nameSuffix = '-%s' % self.appName
|
||||
depends = ', python-appy'
|
||||
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.
|
||||
f = file('postinst', 'w')
|
||||
content = '#!/bin/sh\nset -e\n'
|
||||
for version in self.pythonVersions:
|
||||
content += 'if [ -e /usr/bin/python%s ]\nthen\n ' \
|
||||
'/usr/bin/python%s -m compileall -q ' \
|
||||
'/usr/lib/python%s/%s 2> /dev/null\nfi\n' % \
|
||||
(version, version, version, self.appName)
|
||||
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)
|
||||
# ------------------------------------------------------------------------------
|
|
@ -364,7 +364,10 @@ class CodeAnalysis:
|
|||
# ------------------------------------------------------------------------------
|
||||
class LinesCounter:
|
||||
'''Counts and classifies the lines of code within a folder hierarchy.'''
|
||||
def __init__(self, folderOrModule):
|
||||
defaultExcludes = ('%s.svn' % os.sep, '%s.bzr' % os.sep, '%stmp' % os.sep,
|
||||
'%stemp' % os.sep)
|
||||
|
||||
def __init__(self, folderOrModule, excludes=None):
|
||||
if isinstance(folderOrModule, basestring):
|
||||
# It is the path of some folder
|
||||
self.folder = folderOrModule
|
||||
|
@ -378,12 +381,20 @@ class LinesCounter:
|
|||
True: CodeAnalysis('ZPT (test)')}
|
||||
# Are we currently analysing real or test code?
|
||||
self.inTest = False
|
||||
# Which paths to exclude from the analysis?
|
||||
self.excludes = list(self.defaultExcludes)
|
||||
if excludes: self.excludes += excludes
|
||||
|
||||
def printReport(self):
|
||||
'''Displays on stdout a small analysis report about self.folder.'''
|
||||
for zone in (False, True): self.python[zone].printReport()
|
||||
for zone in (False, True): self.zpt[zone].printReport()
|
||||
|
||||
def isExcluded(self, path):
|
||||
'''Must p_path be excluded from the analysis?'''
|
||||
for excl in self.excludes:
|
||||
if excl in path: return True
|
||||
|
||||
def run(self):
|
||||
'''Let's start the analysis of self.folder.'''
|
||||
# The test markers will allow us to know if we are analysing test code
|
||||
|
@ -394,10 +405,7 @@ class LinesCounter:
|
|||
testMarker4 = '%stests' % os.sep
|
||||
j = os.path.join
|
||||
for root, folders, files in os.walk(self.folder):
|
||||
rootName = os.path.basename(root)
|
||||
if rootName.startswith('.') or \
|
||||
(rootName in ('tmp', 'temp')):
|
||||
continue
|
||||
if self.isExcluded(root): continue
|
||||
# Are we in real code or in test code ?
|
||||
self.inTest = False
|
||||
if root.endswith(testMarker2) or (root.find(testMarker1) != -1) or \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue