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
|
@ -1,17 +1,17 @@
|
||||||
'''This script allows to generate a product from a Appy application.'''
|
'''This script allows to generate a Zope product from a Appy application.'''
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import sys, os.path
|
import sys, os.path
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
from appy.gen.generator import GeneratorError, ZopeGenerator
|
from appy.gen.generator import GeneratorError, ZopeGenerator
|
||||||
from appy.shared.utils import LinesCounter
|
from appy.shared.utils import LinesCounter
|
||||||
|
from appy.shared.packaging import Debianizer
|
||||||
import appy.version
|
import appy.version
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
ERROR_CODE = 1
|
ERROR_CODE = 1
|
||||||
APP_NOT_FOUND = 'Application not found at %s.'
|
APP_NOT_FOUND = 'Application not found at %s.'
|
||||||
WRONG_NG_OF_ARGS = 'Wrong number of arguments.'
|
WRONG_NG_OF_ARGS = 'Wrong number of arguments.'
|
||||||
WRONG_OUTPUT_FOLDER = 'Output folder not found. Please create it first.'
|
|
||||||
C_OPTION = 'Removes from i18n files all labels that are not automatically ' \
|
C_OPTION = 'Removes from i18n files all labels that are not automatically ' \
|
||||||
'generated from your gen-application. It can be useful during ' \
|
'generated from your gen-application. It can be useful during ' \
|
||||||
'development, when you do lots of name changes (classes, ' \
|
'development, when you do lots of name changes (classes, ' \
|
||||||
|
@ -32,26 +32,24 @@ S_OPTION = 'Sorts all i18n labels. If you use this option, among the ' \
|
||||||
'i18n file. When the development is finished, it may be a good ' \
|
'i18n file. When the development is finished, it may be a good ' \
|
||||||
'idea to sort the labels to get a clean and logically ordered ' \
|
'idea to sort the labels to get a clean and logically ordered ' \
|
||||||
'set of translation files.'
|
'set of translation files.'
|
||||||
|
D_OPTION = 'Generates a Debian package for this app. The Debian package will ' \
|
||||||
|
'be generated at the same level as the root application folder.'
|
||||||
|
|
||||||
class GeneratorScript:
|
class GeneratorScript:
|
||||||
'''usage: %prog [options] app outputFolder
|
'''usage: %prog [options] app
|
||||||
|
|
||||||
"app" is the path to your Appy application, which must be a
|
"app" is the path to your Appy application, which must be a
|
||||||
Python package (= a folder containing a file named
|
Python package (= a folder containing a file named
|
||||||
__init__.py). Your app may reside anywhere, but needs to
|
__init__.py). Your app may reside anywhere, but needs to
|
||||||
be accessible by Zope. Typically, it may be or symlinked
|
be accessible by Zope. Typically, it may be or symlinked
|
||||||
in <yourZopeInstance>/lib/python, but not within the
|
in <yourZopeInstance>/lib/python.
|
||||||
generated product, stored or symlinked in
|
|
||||||
<yourZopeInstance>/Products.
|
|
||||||
|
|
||||||
"outputFolder" is the folder where the Zope product will be generated.
|
This command generates a Zope product in <app>/zope, which must be
|
||||||
For example, if you develop your application in
|
or symlinked in <yourZopeInstance>/Products.
|
||||||
/home/gdy/MyProject/MyProject, you typically specify
|
|
||||||
"/home/gdy/MyProject/zope" as outputFolder.
|
|
||||||
'''
|
'''
|
||||||
def manageArgs(self, parser, options, args):
|
def manageArgs(self, parser, options, args):
|
||||||
# Check number of args
|
# Check number of args
|
||||||
if len(args) != 2:
|
if len(args) != 1:
|
||||||
print WRONG_NG_OF_ARGS
|
print WRONG_NG_OF_ARGS
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(ERROR_CODE)
|
sys.exit(ERROR_CODE)
|
||||||
|
@ -59,13 +57,8 @@ class GeneratorScript:
|
||||||
if not os.path.exists(args[0]):
|
if not os.path.exists(args[0]):
|
||||||
print APP_NOT_FOUND % args[0]
|
print APP_NOT_FOUND % args[0]
|
||||||
sys.exit(ERROR_CODE)
|
sys.exit(ERROR_CODE)
|
||||||
# Check existence of outputFolder
|
# Convert app path to an absolute path
|
||||||
if not os.path.exists(args[1]):
|
args[0] = os.path.abspath(args[0])
|
||||||
print WRONG_OUTPUT_FOLDER
|
|
||||||
sys.exit(ERROR_CODE)
|
|
||||||
# Convert all paths in absolute paths
|
|
||||||
for i in (0,1):
|
|
||||||
args[i] = os.path.abspath(args[i])
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
optParser = OptionParser(usage=GeneratorScript.__doc__)
|
optParser = OptionParser(usage=GeneratorScript.__doc__)
|
||||||
|
@ -73,14 +66,26 @@ class GeneratorScript:
|
||||||
dest='i18nClean', default=False, help=C_OPTION)
|
dest='i18nClean', default=False, help=C_OPTION)
|
||||||
optParser.add_option("-s", "--i18n-sort", action='store_true',
|
optParser.add_option("-s", "--i18n-sort", action='store_true',
|
||||||
dest='i18nSort', default=False, help=S_OPTION)
|
dest='i18nSort', default=False, help=S_OPTION)
|
||||||
|
optParser.add_option("-d", "--debian", action='store_true',
|
||||||
|
dest='debian', default=False, help=D_OPTION)
|
||||||
(options, args) = optParser.parse_args()
|
(options, args) = optParser.parse_args()
|
||||||
try:
|
try:
|
||||||
self.manageArgs(optParser, options, args)
|
self.manageArgs(optParser, options, args)
|
||||||
print 'Appy version:', appy.version.verbose
|
print 'Appy version:', appy.version.verbose
|
||||||
print 'Generating Zope product in %s...' % args[1]
|
print 'Generating Zope product in %s/zope...' % args[0]
|
||||||
ZopeGenerator(args[0], args[1], options).run()
|
ZopeGenerator(args[0], options).run()
|
||||||
# Give the user some statistics about its code
|
# Give the user some statistics about its code
|
||||||
LinesCounter(args[0]).run()
|
LinesCounter(args[0], excludes=['%szope' % os.sep]).run()
|
||||||
|
# Generates a Debian package for this app if required
|
||||||
|
if options.debian:
|
||||||
|
app = args[0]
|
||||||
|
appDir = os.path.dirname(app)
|
||||||
|
# Get the app version from zope/version.txt
|
||||||
|
f = file(os.path.join(app, 'zope', 'version.txt'))
|
||||||
|
version = f.read()
|
||||||
|
f.close()
|
||||||
|
version = version[:version.find('build')-1]
|
||||||
|
Debianizer(app, appDir, appVersion=version).run()
|
||||||
except GeneratorError, ge:
|
except GeneratorError, ge:
|
||||||
sys.stderr.write(str(ge))
|
sys.stderr.write(str(ge))
|
||||||
sys.stderr.write('\n')
|
sys.stderr.write('\n')
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# Imports ----------------------------------------------------------------------
|
# Imports ----------------------------------------------------------------------
|
||||||
import os, os.path, sys, shutil, re, zipfile, sys, ftplib, time, subprocess, md5
|
import os, os.path, sys, shutil, re, zipfile, sys, ftplib, time
|
||||||
import appy
|
import appy
|
||||||
from appy.shared import appyPath
|
from appy.shared import appyPath
|
||||||
from appy.shared.utils import FolderDeleter, LinesCounter
|
from appy.shared.utils import FolderDeleter, LinesCounter
|
||||||
|
from appy.shared.packaging import Debianizer
|
||||||
from appy.bin.clean import Cleaner
|
from appy.bin.clean import Cleaner
|
||||||
from appy.gen.utils import produceNiceMessage
|
from appy.gen.utils import produceNiceMessage
|
||||||
|
|
||||||
|
@ -26,34 +27,6 @@ recursive-include appy/gen *
|
||||||
recursive-include appy/pod *
|
recursive-include appy/pod *
|
||||||
recursive-include appy/shared *
|
recursive-include appy/shared *
|
||||||
'''
|
'''
|
||||||
debianInfo = '''Package: python-appy
|
|
||||||
Version: %s
|
|
||||||
Architecture: all
|
|
||||||
Maintainer: Gaetan Delannay <gaetan.delannay@geezteem.com>
|
|
||||||
Installed-Size: %d
|
|
||||||
Depends: python (>= 2.6), python (<< 3.0)
|
|
||||||
Section: python
|
|
||||||
Priority: optional
|
|
||||||
Homepage: http://appyframework.org
|
|
||||||
Description: Appy builds simple but complex web Python apps.
|
|
||||||
'''
|
|
||||||
debianPostInst = '''#!/bin/sh
|
|
||||||
set -e
|
|
||||||
if [ -e /usr/bin/python2.6 ]
|
|
||||||
then
|
|
||||||
/usr/bin/python2.6 -m compileall -q /usr/lib/python2.6/appy 2> /dev/null
|
|
||||||
fi
|
|
||||||
if [ -e /usr/bin/python2.7 ]
|
|
||||||
then
|
|
||||||
/usr/bin/python2.7 -m compileall -q /usr/lib/python2.7/appy 2> /dev/null
|
|
||||||
fi
|
|
||||||
'''
|
|
||||||
debianPreRm = '''#!/bin/sh
|
|
||||||
set -e
|
|
||||||
find /usr/lib/python2.6/appy -name "*.pyc" -delete
|
|
||||||
find /usr/lib/python2.7/appy -name "*.pyc" -delete
|
|
||||||
'''
|
|
||||||
|
|
||||||
def askLogin():
|
def askLogin():
|
||||||
print 'Login: ',
|
print 'Login: ',
|
||||||
login = sys.stdin.readline().strip()
|
login = sys.stdin.readline().strip()
|
||||||
|
@ -242,9 +215,6 @@ class Text2Html:
|
||||||
class Publisher:
|
class Publisher:
|
||||||
'''Publishes Appy on the web.'''
|
'''Publishes Appy on the web.'''
|
||||||
pageBody = re.compile('<body.*?>(.*)</body>', re.S)
|
pageBody = re.compile('<body.*?>(.*)</body>', re.S)
|
||||||
eggVersion = re.compile('version\s*=\s*".*?"')
|
|
||||||
pythonTargets = ('2.4', '2.5')
|
|
||||||
svnServer = 'http://svn.communesplone.org/svn/communesplone/appy'
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.genFolder = '%s/temp' % appyPath
|
self.genFolder = '%s/temp' % appyPath
|
||||||
|
@ -303,66 +273,9 @@ class Publisher:
|
||||||
|
|
||||||
def createDebianRelease(self):
|
def createDebianRelease(self):
|
||||||
'''Creates a Debian package for Appy.'''
|
'''Creates a Debian package for Appy.'''
|
||||||
curdir = os.getcwd()
|
j = os.path.join
|
||||||
# Create a temp folder for creating the Debian files hierarchy.
|
Debianizer(j(self.genFolder, 'appy'), j(appyPath, 'versions'),
|
||||||
srcFolder = os.path.join(self.genFolder, 'debian', 'usr', 'lib')
|
appVersion=self.versionShort).run()
|
||||||
os.makedirs(os.path.join(srcFolder, 'python2.6'))
|
|
||||||
os.makedirs(os.path.join(srcFolder, 'python2.7'))
|
|
||||||
# Copy Appy sources in it
|
|
||||||
py26 = os.path.join(srcFolder, 'python2.6', 'appy')
|
|
||||||
os.rename(os.path.join(self.genFolder, 'appy'), py26)
|
|
||||||
shutil.copytree(py26, os.path.join(srcFolder, 'python2.7', 'appy'))
|
|
||||||
# Create data.tar.gz based on it.
|
|
||||||
debFolder = os.path.join(self.genFolder, 'debian')
|
|
||||||
os.chdir(debFolder)
|
|
||||||
os.system('tar czvf data.tar.gz ./usr')
|
|
||||||
# Get the size of Appy, in Kb.
|
|
||||||
cmd = subprocess.Popen(['du', '-b', '-s', 'usr'],stdout=subprocess.PIPE)
|
|
||||||
size = int(int(cmd.stdout.read().split()[0])/1024.0)
|
|
||||||
# Create control file
|
|
||||||
f = file('control', 'w')
|
|
||||||
f.write(debianInfo % (self.versionShort, size))
|
|
||||||
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 = os.path.join(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 and prerm
|
|
||||||
f = file('postinst', 'w')
|
|
||||||
f.write(debianPostInst)
|
|
||||||
f.close()
|
|
||||||
f = file('prerm', 'w')
|
|
||||||
f.write(debianPreRm)
|
|
||||||
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.deb' % self.versionShort
|
|
||||||
os.system('ar -r %s debian-binary control.tar.gz data.tar.gz' % \
|
|
||||||
debName)
|
|
||||||
os.chdir(curdir)
|
|
||||||
# Move it to folder "versions".
|
|
||||||
os.rename(os.path.join(debFolder, debName),
|
|
||||||
os.path.join(appyPath, 'versions', debName))
|
|
||||||
# Clean temp files
|
|
||||||
FolderDeleter.delete(debFolder)
|
|
||||||
|
|
||||||
def createDistRelease(self):
|
def createDistRelease(self):
|
||||||
'''Create the distutils package.'''
|
'''Create the distutils package.'''
|
||||||
|
|
|
@ -115,12 +115,12 @@ CODE_HEADER = '''# -*- coding: utf-8 -*-
|
||||||
'''
|
'''
|
||||||
class Generator:
|
class Generator:
|
||||||
'''Abstract base class for building a generator.'''
|
'''Abstract base class for building a generator.'''
|
||||||
def __init__(self, application, outputFolder, options):
|
def __init__(self, application, options):
|
||||||
self.application = application
|
self.application = application
|
||||||
# Determine application name
|
# Determine application name
|
||||||
self.applicationName = os.path.basename(application)
|
self.applicationName = os.path.basename(application)
|
||||||
# Determine output folder (where to store the generated product)
|
# Determine output folder (where to store the generated product)
|
||||||
self.outputFolder = outputFolder
|
self.outputFolder = os.path.join(application, 'zope')
|
||||||
self.options = options
|
self.options = options
|
||||||
# Determine templates folder
|
# Determine templates folder
|
||||||
genFolder = os.path.dirname(__file__)
|
genFolder = os.path.dirname(__file__)
|
||||||
|
@ -186,8 +186,13 @@ class Generator:
|
||||||
|
|
||||||
IMPORT_ERROR = 'Warning: error while importing module %s (%s)'
|
IMPORT_ERROR = 'Warning: error while importing module %s (%s)'
|
||||||
SYNTAX_ERROR = 'Warning: error while parsing module %s (%s)'
|
SYNTAX_ERROR = 'Warning: error while parsing module %s (%s)'
|
||||||
|
noVisit = ('tr', 'zope')
|
||||||
def walkModule(self, moduleName):
|
def walkModule(self, moduleName):
|
||||||
'''Visits a given (sub-*)module into the application.'''
|
'''Visits a given (sub-*)module into the application.'''
|
||||||
|
# Some sub-modules must not be visited
|
||||||
|
for nv in self.noVisit:
|
||||||
|
nvName = '%s.%s' % (self.applicationName, nv)
|
||||||
|
if moduleName == nvName: return
|
||||||
try:
|
try:
|
||||||
exec 'import %s' % moduleName
|
exec 'import %s' % moduleName
|
||||||
exec 'moduleObj = %s' % moduleName
|
exec 'moduleObj = %s' % moduleName
|
||||||
|
@ -359,7 +364,7 @@ class ZopeGenerator(Generator):
|
||||||
versionRex = re.compile('(.*?\s+build)\s+(\d+)')
|
versionRex = re.compile('(.*?\s+build)\s+(\d+)')
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
# Determine version number
|
# Determine version number
|
||||||
self.version = '0.1 build 1'
|
self.version = '0.1.0 build 1'
|
||||||
versionTxt = os.path.join(self.outputFolder, 'version.txt')
|
versionTxt = os.path.join(self.outputFolder, 'version.txt')
|
||||||
if os.path.exists(versionTxt):
|
if os.path.exists(versionTxt):
|
||||||
f = file(versionTxt)
|
f = file(versionTxt)
|
||||||
|
|
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:
|
class LinesCounter:
|
||||||
'''Counts and classifies the lines of code within a folder hierarchy.'''
|
'''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):
|
if isinstance(folderOrModule, basestring):
|
||||||
# It is the path of some folder
|
# It is the path of some folder
|
||||||
self.folder = folderOrModule
|
self.folder = folderOrModule
|
||||||
|
@ -378,12 +381,20 @@ class LinesCounter:
|
||||||
True: CodeAnalysis('ZPT (test)')}
|
True: CodeAnalysis('ZPT (test)')}
|
||||||
# Are we currently analysing real or test code?
|
# Are we currently analysing real or test code?
|
||||||
self.inTest = False
|
self.inTest = False
|
||||||
|
# Which paths to exclude from the analysis?
|
||||||
|
self.excludes = list(self.defaultExcludes)
|
||||||
|
if excludes: self.excludes += excludes
|
||||||
|
|
||||||
def printReport(self):
|
def printReport(self):
|
||||||
'''Displays on stdout a small analysis report about self.folder.'''
|
'''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.python[zone].printReport()
|
||||||
for zone in (False, True): self.zpt[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):
|
def run(self):
|
||||||
'''Let's start the analysis of self.folder.'''
|
'''Let's start the analysis of self.folder.'''
|
||||||
# The test markers will allow us to know if we are analysing test code
|
# The test markers will allow us to know if we are analysing test code
|
||||||
|
@ -394,10 +405,7 @@ class LinesCounter:
|
||||||
testMarker4 = '%stests' % os.sep
|
testMarker4 = '%stests' % os.sep
|
||||||
j = os.path.join
|
j = os.path.join
|
||||||
for root, folders, files in os.walk(self.folder):
|
for root, folders, files in os.walk(self.folder):
|
||||||
rootName = os.path.basename(root)
|
if self.isExcluded(root): continue
|
||||||
if rootName.startswith('.') or \
|
|
||||||
(rootName in ('tmp', 'temp')):
|
|
||||||
continue
|
|
||||||
# Are we in real code or in test code ?
|
# Are we in real code or in test code ?
|
||||||
self.inTest = False
|
self.inTest = False
|
||||||
if root.endswith(testMarker2) or (root.find(testMarker1) != -1) or \
|
if root.endswith(testMarker2) or (root.find(testMarker1) != -1) or \
|
||||||
|
|
Loading…
Reference in a new issue