Added script eggify.py for wrapping a Python module into an egg, and plenty of minor improvements and refactorings.
This commit is contained in:
parent
aea19a819e
commit
52816ec343
23 changed files with 2048 additions and 1760 deletions
|
@ -6,7 +6,7 @@ from appy.shared.utils import FolderDeleter, cleanFolder
|
|||
# ------------------------------------------------------------------------------
|
||||
class Cleaner:
|
||||
def run(self, verbose=True):
|
||||
cleanFolder(appyPath, verbose=True)
|
||||
cleanFolder(appyPath, verbose=verbose)
|
||||
# Remove all files in temp folders
|
||||
for tempFolder in ('%s/temp' % appyPath,
|
||||
'%s/pod/test/temp' % appyPath):
|
||||
|
|
178
bin/eggify.py
Normal file
178
bin/eggify.py
Normal file
|
@ -0,0 +1,178 @@
|
|||
'''This sript allows to wrap a Python module into an egg.'''
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
import os, os.path, sys, zipfile, appy
|
||||
from appy.bin.clean import Cleaner
|
||||
from appy.shared.utils import FolderDeleter, copyFolder
|
||||
from optparse import OptionParser
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
class EggifierError(Exception): pass
|
||||
ERROR_CODE = 1
|
||||
eggInfo = '''from setuptools import setup, find_packages
|
||||
import os
|
||||
setup(name = "%s", version = "%s", description = "%s",
|
||||
long_description = "%s",
|
||||
author = "%s", author_email = "%s",
|
||||
license = "GPL", keywords = "plone, appy", url = '%s',
|
||||
classifiers = ["Framework :: Appy", "Programming Language :: Python",],
|
||||
packages=find_packages(exclude=['ez_setup']), include_package_data = True,
|
||||
namespace_packages=['%s'], zip_safe = False,
|
||||
install_requires=['setuptools'],)'''
|
||||
initInfo = '''
|
||||
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
|
||||
try:
|
||||
__import__('pkg_resources').declare_namespace(__name__)
|
||||
except ImportError:
|
||||
from pkgutil import extend_path
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
'''
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
class EggifyScript:
|
||||
'''usage: python eggify.py pythonModule [options]
|
||||
pythonModule is the path to a Python module or the name of a Python file.
|
||||
|
||||
Available options are:
|
||||
-a --appy If specified, the Appy module (light version, without
|
||||
test code) will be included in the egg.
|
||||
-r --result The path where to create the egg (defaults to the
|
||||
current working directory)
|
||||
-p --products If specified, the module will be packaged in the
|
||||
"Products" namespace.
|
||||
-v --version Egg version. Defaults to 1.0.0.
|
||||
'''
|
||||
def createSetupFile(self, eggTempFolder):
|
||||
'''Creates the setup.py file in the egg.'''
|
||||
content = eggInfo % (self.moduleName, self.version, 'Appy module',
|
||||
'Appy module', 'Gaetan Delannay',
|
||||
'gaetan.delannay AT gmail.com',
|
||||
'http://appyframework.org',
|
||||
self.moduleName.split('.')[0])
|
||||
f = file(os.path.join(eggTempFolder, 'setup.py'), 'w')
|
||||
f.write(content)
|
||||
f.close()
|
||||
|
||||
def createInitFile(self, eggTempFolder):
|
||||
'''Creates the ez_setup-compliant __init__ files.'''
|
||||
initPath = os.path.join(eggTempFolder,self.moduleName.split('.')[0])
|
||||
f = file(os.path.join(initPath, '__init__.py'), 'w')
|
||||
f.write(initInfo)
|
||||
f.close()
|
||||
|
||||
def getEggName(self):
|
||||
'''Creates the egg name.'''
|
||||
return '%s-%s.egg' % (self.moduleName, self.version)
|
||||
|
||||
zipExclusions = ('.bzr', 'doc', 'test', 'versions')
|
||||
def dirInZip(self, dir):
|
||||
'''Returns True if the p_dir must be included in the zip.'''
|
||||
for exclusion in self.zipExclusions:
|
||||
if dir.endswith(exclusion) or ('/%s/' % exclusion in dir):
|
||||
return False
|
||||
return True
|
||||
|
||||
def zipResult(self, eggFullName, eggTempFolder):
|
||||
'''Zips the result and removes the egg temp folder.'''
|
||||
zipFile = zipfile.ZipFile(eggFullName, 'w', zipfile.ZIP_DEFLATED)
|
||||
# Put the Python module inside the egg.
|
||||
prefix = os.path.dirname(eggTempFolder)
|
||||
for dir, dirnames, filenames in os.walk(eggTempFolder):
|
||||
for f in filenames:
|
||||
fileName = os.path.join(dir, f)
|
||||
zipFile.write(fileName, fileName[len(prefix):])
|
||||
# Put the Appy module inside it if required.
|
||||
if self.includeAppy:
|
||||
eggPrefix = '%s/%s' % (eggTempFolder[len(prefix):],
|
||||
self.moduleName.replace('.', '/'))
|
||||
# Where is Appy?
|
||||
appyPath = os.path.dirname(appy.__file__)
|
||||
appyPrefix = os.path.dirname(appyPath)
|
||||
# Clean the Appy folder
|
||||
Cleaner().run(verbose=False)
|
||||
# Insert appy files into the zip
|
||||
for dir, dirnames, filenames in os.walk(appyPath):
|
||||
if not self.dirInZip(dir): continue
|
||||
for f in filenames:
|
||||
fileName = os.path.join(dir, f)
|
||||
zipName = eggPrefix + fileName[len(appyPrefix):]
|
||||
zipFile.write(fileName, zipName)
|
||||
zipFile.close()
|
||||
# Remove the temp egg folder.
|
||||
FolderDeleter.delete(eggTempFolder)
|
||||
|
||||
def eggify(self):
|
||||
'''Let's wrap a nice Python module into an ugly egg.'''
|
||||
j = os.path.join
|
||||
# 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 checkArgs(self, options, args):
|
||||
# Check that we have the correct number of args.
|
||||
if len(args) != 1: raise EggifierError('Wrong number of arguments.')
|
||||
# Check that the arg corresponds to an existing Python module
|
||||
if not os.path.exists(args[0]):
|
||||
raise EggifierError('Path "%s" does not correspond to an ' \
|
||||
'existing Python package.' % args[0])
|
||||
self.pythonModule = args[0]
|
||||
# At present I only manage Python modules, not 1-file Python packages.
|
||||
if not os.path.isdir(self.pythonModule):
|
||||
raise EggifierError('"%s" is not a folder. One-file Python ' \
|
||||
'packages are not supported yet.' % args[0])
|
||||
self.eggFolder = options.result
|
||||
if not os.path.exists(self.eggFolder):
|
||||
raise EggifierError('"%s" does not exist. Please create this ' \
|
||||
'folder first.' % self.eggFolder)
|
||||
self.includeAppy = options.appy
|
||||
self.inProducts = options.products
|
||||
self.version = options.version
|
||||
self.moduleName = os.path.basename(self.pythonModule)
|
||||
if self.inProducts:
|
||||
self.moduleName = 'Products.' + self.moduleName
|
||||
self.eggName = self.getEggName()
|
||||
|
||||
def run(self):
|
||||
optParser = OptionParser(usage=EggifyScript.__doc__)
|
||||
optParser.add_option("-r", "--result", dest="result",
|
||||
help="The folder where to create the egg",
|
||||
default=os.getcwd(), metavar="RESULT",
|
||||
type='string')
|
||||
optParser.add_option("-a", "--appy", action="store_true",
|
||||
help="Includes the Appy module in the egg")
|
||||
optParser.add_option("-p", "--products", action="store_true",
|
||||
help="Includes the module in the 'Products' " \
|
||||
"namespace")
|
||||
optParser.add_option("-v", "--version", dest="version",
|
||||
help="The module version", default='1.0.0',
|
||||
metavar="VERSION", type='string')
|
||||
options, args = optParser.parse_args()
|
||||
try:
|
||||
self.checkArgs(options, args)
|
||||
self.eggify()
|
||||
except EggifierError, ee:
|
||||
sys.stderr.write(str(ee) + '\nRun eggify.py -h for getting help.\n')
|
||||
sys.exit(ERROR_CODE)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
EggifyScript().run()
|
||||
# ------------------------------------------------------------------------------
|
|
@ -395,7 +395,7 @@ class Publisher:
|
|||
f.close()
|
||||
|
||||
privateScripts = ('publish.py', 'zip.py', 'runOpenOffice.sh')
|
||||
def prepareGenFolder(self):
|
||||
def prepareGenFolder(self, minimalist=False):
|
||||
'''Creates the basic structure of the temp folder where the appy
|
||||
website will be generated.'''
|
||||
# Reinitialise temp folder where the generated website will be dumped
|
||||
|
@ -413,6 +413,8 @@ class Publisher:
|
|||
# Remove some scripts from bin
|
||||
for script in self.privateScripts:
|
||||
os.remove('%s/bin/%s' % (genSrcFolder, script))
|
||||
if minimalist:
|
||||
FolderDeleter.delete('%s/pod/test' % genSrcFolder)
|
||||
# Write the appy version into the code itself (in appy/version.py)'''
|
||||
print 'Publishing version %s...' % self.versionShort
|
||||
# Dump version info in appy/version.py
|
||||
|
@ -436,7 +438,9 @@ class Publisher:
|
|||
# Perform a small analysis on the Appy code
|
||||
LinesCounter(appy).run()
|
||||
print 'Generating site in %s...' % self.genFolder
|
||||
self.prepareGenFolder()
|
||||
minimalist = askQuestion('Minimalist (shipped without tests)?',
|
||||
default='no')
|
||||
self.prepareGenFolder(minimalist)
|
||||
self.createDocToc()
|
||||
self.applyTemplate()
|
||||
self.createZipRelease()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue