Exemplo n.º 1
0
    def load(self):
        """ Loads the plug-in into memory, but does not yet install it. Will return None on success, otherwise a message (string) that says why the plug-in could not be loaded. """
        print 'Loading plug-in: %s at %s' % (self._name, self._path)

        assert os.path.exists(self._path)

        # Grab the Properties.py
        self._properties = PropertiesObject(
            self.serverSidePath('Properties.py'))
        if not self._properties['willRun']:
            return self._properties['willNotRunReason']

        # Update sys.path
        if not self._dir in sys.path:
            sys.path.append(self._dir)

        # Import the package
        self._module = __import__(self._name, globals(), [], [])

        # Inspect it and verify some required conventions
        if not hasattr(self._module, 'InstallInWebKit'):
            raise PlugInError, "Plug-in '%s' in '%s' has no InstallInWebKit() function." % (
                self._name, self._dir)

        # Give the module a pointer back to us
        setattr(self._module, 'plugIn', self)

        # Make a directory for it in Cache/
        cacheDir = os.path.join(self._appServer.serverSidePath(), 'Cache',
                                self._name)
        if not os.path.exists(cacheDir):
            os.mkdir(cacheDir)

        self.setUpExamplePages()
Exemplo n.º 2
0
    def initVersions(self):
        """Get and store versions.

        Initialize attributes that store the Webware and WebKit versions as
        both tuples and strings. These are stored in the Properties.py files.
        """
        from MiscUtils.PropertiesObject import PropertiesObject
        props = PropertiesObject(
            os.path.join(self.webwarePath(), 'Properties.py'))
        self._webwareVersion = props['version']
        self._webwareVersionString = props['versionString']
        props = PropertiesObject(
            os.path.join(self.webKitPath(), 'Properties.py'))
        self._webKitVersion = props['version']
        self._webKitVersionString = props['versionString']
Exemplo n.º 3
0
 def version(self):
     """Return WebKit version."""
     if not hasattr(self, '_webKitVersionString'):
         from MiscUtils.PropertiesObject import PropertiesObject
         props = PropertiesObject(os.path.join(self.webKitPath(), 'Properties.py'))
         self._webKitVersionString = props['versionString']
     return self._webKitVersionString
Exemplo n.º 4
0
 def detectComponents(self):
     print 'Scanning for components...'
     filenames = os.listdir('.')
     maxLen = max(
         filter(
             None,
             map(lambda name: os.path.isdir(name) and len(name),
                 filenames)))
     count = 0
     needPrint = 0
     for filename in os.listdir('.'):
         if os.path.isdir(filename):
             propName = os.path.join(filename, 'Properties.py')
             displayName = string.ljust(filename, maxLen)
             if os.path.exists(propName):
                 comp = PropertiesObject(propName)
                 comp['filename'] = filename
                 self._comps.append(comp)
                 print '  yes', displayName,
             else:
                 print '   no', displayName,
             if count % 2 == 1:
                 print
                 needPrint = 0
             else:
                 needPrint = 1
             count = count + 1
     if needPrint:
         print
     print
     self._comps.sort(lambda a, b: cmp(a['name'], b['name']))
Exemplo n.º 5
0
 def __init__(self):
     self._props = PropertiesObject('Properties.py')
     self._props['dirname'] = '.'
     self._comps = []
     self._htHeader, self._htFooter = self.htHeaderAndFooter()
     from DocSupport.pytp import PyTP
     self._pytp = PyTP()
     from DocSupport.autotoc import AutoToC
     self._autotoc = AutoToC()
Exemplo n.º 6
0
	def __init__(self):
		self._props = PropertiesObject('Properties.py')
		self._props['dirname'] = '.'
		self._comps = []
		self._htHeader, self._htFooter = self.htHeaderAndFooter()
		from DocSupport.pytp import PyTP
		self._pytp = PyTP()
		from DocSupport.autotoc import AutoToC
		self._autotoc = AutoToC()
Exemplo n.º 7
0
	def detectComponents(self):
		print 'Scanning for components...'
		dirNames = filter(lambda dir: not dir.startswith('.')
				and os.path.isdir(dir), os.listdir(os.curdir))
		dirNames.sort()
		self._maxCompLen = max(map(len, dirNames))
		oldPyVersion = 0
		column = 0
		for dirName in dirNames:
			propName = dirName + '/Properties.py'
			try:
				print dirName.ljust(self._maxCompLen, '.'),
			except TypeError:
				print dirName.ljust(self._maxCompLen),
			if os.path.exists(propName):
				comp = PropertiesObject(propName)
				comp['dirname'] = dirName
				for key in self._props.keys():
					if not comp.has_key(key):
						comp[key] = self._props[key]
				if sys.version_info[:3] < comp['requiredPyVersion']:
					oldPyVersion += 1
					print 'no*',
				else:
					self._comps.append(comp)
					print 'yes',
			else:
				print 'no ',
			if column < 2 and not self._verbose:
				print '   ',
				column += 1
			else:
				print
				column = 0
		if column:
			print
		if oldPyVersion:
			print "* some components require a newer Python version"
		self._comps.sort(lambda a, b: cmp(a['name'], b['name']))
		print
Exemplo n.º 8
0
    def load(self, verbose=True):
        """Loads the plug-in into memory, but does not yet install it.

        Will return None on success, otherwise a message (string) that says
        why the plug-in could not be loaded.
        """
        if verbose:
            print(f'Loading plug-in: {self._name} at {self._path}')

        # Grab the Properties.py
        self._properties = PropertiesObject(
            self.serverSidePath('Properties.py'))

        if self._builtin and 'version' not in self._properties:
            self._properties['version'] = self._app._webwareVersion
            self._properties['versionString'] = self._app._webwareVersionString

        if not self._properties['willRun']:
            return self._properties['willNotRunReason']

        # Update sys.path
        if self._dir not in sys.path:
            sys.path.append(self._dir)

        # Inspect it and verify some required conventions
        if not hasattr(self._module, 'installInWebware'):
            raise PlugInError(f"Plug-in '{self._name!r}' in {self._dir!r}"
                              " has no installInWebware() function.")

        # Give the module a pointer back to us
        setattr(self._module, 'plugIn', self)

        # Make a subdirectory for it in the Cache directory:
        if not os.path.exists(self._cacheDir):
            os.mkdir(self._cacheDir)

        self.setUpExamplePages()
Exemplo n.º 9
0
    def initVersions(self):
        """Get and store versions.

        Initialize attributes that stores the Webware version as
        both tuple and string. These are stored in the Properties.py files.
        """
        from MiscUtils.PropertiesObject import PropertiesObject
        props = PropertiesObject(
            os.path.join(self.webwarePath(), 'Properties.py'))
        self._webwareVersion = props['version']
        self._webwareVersionString = props['versionString']
        if tuple(sys.version_info) < tuple(props['requiredPyVersion']):
            pythonVersion = '.'.join(map(str, sys.version_info))
            requiredVersion = props['requiredPyVersionString']
            raise RuntimeError(
                f' Required Python version is {requiredVersion},'
                f' but actual version is {pythonVersion}.')
Exemplo n.º 10
0
	def release_current(self):

		progPath = os.path.join(os.getcwd(), sys.argv[0])  # the location of this script
		webwarePath = os.path.dirname(os.path.dirname(progPath))  # because we're in Webware/bin/
		parentPath = os.path.dirname(webwarePath)  # where the tarball will land

		self.chdir(webwarePath)

		if os.path.exists('_installed'):
			self.error('This Webware has already been installed.')

		from MiscUtils.PropertiesObject import PropertiesObject
		props = PropertiesObject(os.path.join(webwarePath, 'Properties.py'))
		ver = props['versionString']
		print 'Webware version is:', ver

		self.run('cvs update -dP')  # get new directories; prune empty ones

		try:
			tempName = os.tmpnam()
			os.mkdir(tempName)
			self.run('cp -pr %s %s' % (webwarePath, tempName))

			# Get rid of CVS files
			self.run("find %s -name '.cvs*' -exec rm {} \;" % tempName)
			self.run("rm -rf `find %s -name CVS -print`" % tempName)

			self.chdir(tempName)
			pkgName = 'Webware-%s.tar.gz' % ver
			self.run('tar czf %s Webware' % pkgName)

			# Put the results next to the Webware directory
			self.run('cp %s %s' % (pkgName, parentPath))

			assert os.path.exists(os.path.join(parentPath, pkgName))

		finally:
			# Clean up
			self.run('rm -rf %s' % tempName)

		self.writeGoodBye(locals())
Exemplo n.º 11
0
 def detectComponents(self):
     print
     print 'Scanning for components...'
     dirNames = [
         dir for dir in os.listdir(os.curdir)
         if not dir.startswith('.') and os.path.isdir(dir)
     ]
     self._maxCompLen = max(map(len, dirNames))
     oldPyVersion = False
     column = 0
     for dirName in sorted(dirNames):
         propName = dirName + '/Properties.py'
         try:
             print dirName.ljust(self._maxCompLen, '.'),
         except TypeError:
             print dirName.ljust(self._maxCompLen),
         if os.path.exists(propName):
             comp = PropertiesObject(propName)
             comp['dirname'] = dirName
             for key in self._props:
                 if key not in comp:
                     comp[key] = self._props[key]
             if sys.version_info[:3] < comp['requiredPyVersion']:
                 oldPyVersion = True
                 print 'no*',
             else:
                 self._comps.append(comp)
                 print 'yes',
         else:
             print 'no ',
         if column < 2 and not self._verbose:
             print '   ',
             column += 1
         else:
             print
             column = 0
     if column:
         print
     if oldPyVersion:
         print "* some components require a newer Python version"
     self._comps.sort(key=itemgetter('name'))
Exemplo n.º 12
0
	def load(self):
		"""Loads the plug-in into memory, but does not yet install it.

		Will return None on success, otherwise a message (string) that says
		why the plug-in could not be loaded.

		"""
		print 'Loading plug-in: %s at %s' % (self._name, self._path)

		assert os.path.exists(self._path)

		# Grab the Properties.py
		self._properties = PropertiesObject(self.serverSidePath('Properties.py'))
		if not self._properties['willRun']:
			return self._properties['willNotRunReason']

		# Update sys.path
		if not self._dir in sys.path:
			sys.path.append(self._dir)

		# Import the package
		self._module = __import__(self._name, globals(), [], [])

		# Inspect it and verify some required conventions
		if not hasattr(self._module, 'InstallInWebKit'):
			raise PlugInError, \
				"Plug-in '%s' in '%s' has no InstallInWebKit() function." \
				% (self._name, self._dir)

		# Give the module a pointer back to us
		setattr(self._module, 'plugIn', self)

		# Make a subdirectory for it in the Cache directory:
		if not os.path.exists(self._cacheDir):
			os.mkdir(self._cacheDir)

		self.setUpDocContext()
		self.setUpExamplePages()
Exemplo n.º 13
0
 def __init__(self, path=None, settings=None, development=None):
     ConfigurableForServerSidePath.__init__(self)
     if path is None:
         path = os.getcwd()
     self._serverSidePath = os.path.abspath(path)
     self._webwarePath = os.path.abspath(os.path.dirname(__file__))
     if development is None:
         development = bool(os.environ.get('WEBWARE_DEVELOPMENT'))
     self._development = development
     appConfig = self.config()
     if settings:
         appConfig.update(settings)
     self._cacheDir = self.serverSidePath(
         self.setting('CacheDir') or 'Cache')
     from MiscUtils.PropertiesObject import PropertiesObject
     props = PropertiesObject(
         os.path.join(self._webwarePath, 'Properties.py'))
     self._webwareVersion = props['version']
     self._webwareVersionString = props['versionString']
     self._imp = MockImportManager()
     for path in (self._cacheDir, ):
         if path and not os.path.exists(path):
             os.makedirs(path)
Exemplo n.º 14
0
    def replaceInFile(self, filename):
        data = open(filename).read()
        newdata = self.replaceInStr(data)
        if data == newdata:
            if verbose:
                print 'Unchanged ' + filename
        else:
            print 'Updating ' + filename
            open(filename, 'w').write(newdata)

    def replaceGlob(self, pattern):
        for file in glob(pattern):
            if os.path.exists(file):
                self.replaceInFile(file)

po = PropertiesObject()
po.loadValues(version=version, releaseDate=releaseDate)
po.createVersionString()

if po['versionString'] == 'X.Y':
    print "Please set the version."
    sys.exit(1)
elif po['releaseDate'] == '@@/@@/@@':
    print "Please set the release Date."
    sys.exit(1)

propReplace = Replacer()
propReplace.add(r"(version\s*=)\s*.*",  r"\g<1> %s" % repr(version))
propReplace.add(r"(releaseDate\s*=)\s*.*", r"\g<1> %s" % repr(releaseDate))

htmlReplace = Replacer()
Exemplo n.º 15
0
	def replaceInFile(self, filename):
		data = open(filename).read()
		newdata = self.replaceInStr(data)
		if data == newdata:
			if verbose:
				print 'Unchanged ' + filename
		else:
			print 'Updating ' + filename
			open(filename, 'w').write(newdata)

	def replaceGlob(self, pattern):
		for file in glob(pattern):
			if os.path.exists(file):
				self.replaceInFile(file)

po = PropertiesObject()
po.loadValues({'version': version, 'releaseDate': releaseDate})
po.createVersionString()

if po['versionString'] == 'X.Y':
	print "Please set the version."
	sys.exit(1)
elif po['releaseDate'] == '@@/@@/@@':
	print "Please set the release Date."
	sys.exit(1)

propReplace = Replacer()
propReplace.add(r"(version\s*=)\s*.*",  r"\g<1> %s" % repr(version))
propReplace.add(r"(releaseDate\s*=)\s*.*", r"\g<1> %s" % repr(releaseDate))

htmlReplace = Replacer()
Exemplo n.º 16
0
def main():
    po = PropertiesObject()
    po.loadValues(version=version, releaseDate=releaseDate)
    po.createVersionString()

    if po['versionString'] == 'X.Y':
        print "Please set the version."
        sys.exit(1)
    elif po['releaseDate'] == '@@/@@/@@':
        print "Please set the release Date."
        sys.exit(1)

    propReplace = Replacer()
    propReplace.add(r"(version\s*=)\s*.*", r"\g<1> %s" % repr(version))
    propReplace.add(r"(releaseDate\s*=)\s*.*", r"\g<1> %s" % repr(releaseDate))

    htmlReplace = Replacer()
    htmlReplace.add(
        r"<!--\s*version\s*-->[^<]*<!--\s*/version\s*-->",
        r"<!-- version --> %s <!-- /version -->" % po['versionString'])
    htmlReplace.add(
        r"<!--\s*relDate\s*-->[^<]*<!--\s*/relDate\s*-->",
        r"<!-- relDate --> %s <!-- /relDate -->" % po['releaseDate'])

    rstReplace = Replacer()
    rstReplace.add(r"^:Version:.*$", ":Version: %s" % po['versionString'])
    rstReplace.add(r"^:Released:.*$", ":Released: %s" % po['releaseDate'])

    phtmlReplace = Replacer()
    phtmlReplace.add(r"(<%.*)' \+ versionString \+ '(.*%>)",
                     r"\g<1>%s\g<2>" % po['versionString'])
    phtmlReplace.add(r"<% versionString %>", po['versionString'])
    phtmlReplace.add(r"<% releaseDate %>", po['releaseDate'])

    twillReplace = Replacer()
    twillReplace.add(r"^setglobal version .*$",
                     r"setglobal version %s" % po['versionString'])
    twillReplace.add(r"^setglobal date .*$",
                     r"setglobal date %s" % po['releaseDate'])
    twillReplace.add(r"^# if release ", '')

    if setVersion:

        # Replace in Properties files:
        propReplace.replaceGlob('Properties.py')
        propReplace.replaceGlob('*/Properties.py')

        # Replace in existing HTML:
        htmlReplace.replaceGlob('*/Docs/*.html')
        htmlReplace.replaceGlob('Docs/*.html')

        # Replace in reStructuredText files:
        rstReplace.replaceGlob('*/Docs/*.txt')
        rstReplace.replaceGlob('Docs/*.txt')

        # Replace in global README file:
        rstReplace.replaceGlob('_README')

        # Replace in twill test scripts:
        twillReplace.replaceGlob('WebKit/Tests/twill/*.twill')

    # Process release notes:

    if setVersion or newRelease:
        template = open('DocSupport/RelNotesTemplate.phtml', 'rb').read()
        infile = 'RelNotes-X.Y.phtml'
        outfile = infile.replace('X.Y', po['versionString'])
        for filename in ['Docs/' + infile] + glob('*/Docs/' + infile):
            if verbose:
                print "Processing " + filename
            current = open(filename, 'rb').read()
            if current == template:
                if newRelease:
                    print "Kept empty " + filename
                    continue
                else:
                    print "Removing empty " + filename
                    if os.system('git rm ' + filename):
                        print "git rm not possible."
                        os.remove(filename)
            else:
                if newRelease:
                    phtmlReplace.replaceInFile(filename)
                newName = os.path.join(os.path.split(filename)[0], outfile)
                print "Renaming %s to %s" % (filename, outfile)
                if os.system('git mv -f %s %s' % (filename, newName)):
                    print "git mv not possible."
                    os.rename(filename, newName)
                if newRelease:
                    print "Creating empty " + filename
                    open(filename, 'wb').write(template)
                    if os.system('git add ' + filename):
                        print "git add not possible."
Exemplo n.º 17
0
    def buildRelease(self):
        """Prepare a release by extracting files from the repository.

        You can specify a tag name on the command line, like

          > bin/ReleaseHelper.py tag=1.1.2

        This will extract the files tagged with 1.1.2 and build the
        tarball Webware-1.1.2.tar.gz in your parent directory.

        This means the release will match exactly what is in the repository,
        and reduces the risk of local changes, modified files, or new
        files which are not in the repository from showing up in the release.
        """

        tag = self._args.get('tag')
        pkg = self._args.get('pkg')
        pkgType = 'zip archive' if pkg == 'zip' else 'tarball'
        if tag:
            print "Creating %s from tag %s ..." % (pkgType, tag)
        else:
            print "Creating %s from current workspace..." % pkgType

        # the location of this script:
        progPath = os.path.join(os.getcwd(), sys.argv[0])
        # we assume this script is located in Webware/bin/
        webwarePath = os.path.dirname(os.path.dirname(progPath))
        # make the Webware directory our current directory
        self.chdir(webwarePath)
        # the tarball will land in its parent directory:
        tarDir = os.pardir

        if webwarePath not in sys.path:
            sys.path.insert(1, webwarePath)
        from MiscUtils.PropertiesObject import PropertiesObject

        target = 'Release'
        try:
            os.mkdir(target)
        except OSError:
            print "Staging directory already exists:", target
            print "Please remove this directory."
            return

        cleanup = [target]

        source = 'tags/%s' % tag if tag else 'HEAD'

        try:
            self.run('git archive %s | tar -x -C %s' % (source, target))
            if not os.path.exists(target):
                print "Unable to extract from %r" % source
                if tag:
                    print "Perhaps the tag %r does not exist." % tag
                self.error()
            propertiesFile = os.path.join(target, 'Properties.py')
            if not os.path.exists(propertiesFile):
                self.error('Properties.py not found.')
            props = PropertiesObject(propertiesFile)
            if props.get('name') != 'Webware for Python':
                self.error('This is not a Webware package.')
            ver = props['versionString']

            print "Webware version is:", ver

            if not tag:
                # timestamp for time of release used to in versioning the file
                year, month, day = time.localtime(time.time())[:3]
                datestamp = "%04d%02d%02d" % (year, month, day)
                # drop leading 2 digits from year. (Ok, itn's not Y2K but it
                # is short and unique in a narrow time range of 100 years.)
                datestamp = datestamp[2:]
                ver += "-" + datestamp
                print "Packaged release will be:", ver

            pkgDir = "Webware-%s" % ver

            if os.path.exists(pkgDir):
                self.error("%s is in the way, please remove it." % pkgDir)

            # rename the target to the pkgDir so the extracted parent
            # directory from the tarball will be unique to this package.
            self.run("mv %s %s" % (target, pkgDir))

            cleanup.append(pkgDir)

            pkgExt = '.zip' if pkg == 'zip' else '.tar.gz'
            pkgName = os.path.join(pkgDir + pkgExt)

            # cleanup .git files
            self.run("find %s -name '.git*' -exec rm {} \;" % pkgDir)

            # We could cleanup any other files not part of this release here.
            # (For instance, we could create releases without documentation).

            # We could also create additional files to be part of this release
            # without being part of the repository, for instance documentation
            # that is automatically created from markup.

            pkgPath = os.path.join(tarDir, pkgName)

            if os.path.exists(pkgPath):
                self.error("%s is in the way, please remove it." % pkgPath)

            tarCmd = 'zip -qr' if pkg == 'zip' else 'tar -czf'
            self.run('%s %s %s' % (tarCmd, pkgPath, pkgDir))

            if not os.path.exists(pkgPath):
                self.error('Could not create %s.' % pkgType)

        finally:  # Clean up
            for path in cleanup:
                if os.path.exists(path):
                    self.run('rm -rf ' + path)

        print
        print "file:", pkgName
        print "dir:", os.path.abspath(tarDir)
        print "size:", os.path.getsize(pkgPath), 'Bytes'
        print
        print 'Success.'
        print
Exemplo n.º 18
0
	def buildRelease(self):
		"""Prepare a release by using the SVN export approach.

		This is used when a tag name is specified on the command line, like

			> bin/ReleaseHelper.py tag=Release-0.9b3

		This will export the SVN files tagged with Release-0_9b3 and build the
		tarball Webware-0.9b3.tar.gz in your parent directory.

		This means the release will match exactly what is in the SVN,
		and reduces the risk of local changes, modified files, or new
		files which are not in SVN from showing up in the release.

		"""

		url = self._args.get('url', ' http://svn.w4py.org/Webware/tags')

		tag = self._args.get('tag', None)
		if tag:
			print "Creating tarball from tag %s ..." % tag
		else:
			print "Creating tarball from current workspace..."

		# the location of this script:
		progPath = os.path.join(os.getcwd(), sys.argv[0])
		# we assume this script is located in Webware/bin/
		webwarePath = os.path.dirname(os.path.dirname(progPath))
		# make the Webware directory our current directory
		self.chdir(webwarePath)
		# the tarball will land in its parent directory:
		tarDir = os.pardir

		if webwarePath not in sys.path:
			sys.path.insert(1, webwarePath)
		from MiscUtils.PropertiesObject import PropertiesObject

		target = 'ReleaseHelper-Export'
		if os.path.exists(target):
			print "There is incomplete ReleaseHelper data in:", target
			print "Please remove this directory."
			return 1

		cleanup = [target]

		if tag:
			source = '%s/%s' % (url, tag)
		else:
			source = '.'

		try:
			self.run('svn export -q %s %s' % (source, target))
			if not os.path.exists(target):
				print "Unable to export from %r" % source
				if tag:
					print "Perhaps the tag %r does not exist." % tag
				self.error()
			propertiesFile = os.path.join(target, 'Properties.py')
			if not os.path.exists(propertiesFile):
				self.error('Properties.py not found.')
			props = PropertiesObject(propertiesFile)
			if props.get('name', None) != 'Webware for Python':
				self.error('This is not a Webware package.')
			ver = props['versionString']

			print "Webware version is:", ver

			if not tag:
				# timestamp for time of release used to in versioning the file
				year, month, day = time.localtime(time.time())[:3]
				datestamp = "%04d%02d%02d" % (year, month, day)
				# drop leading 2 digits from year. (Ok, itn's not Y2K but it
				# is short and unique in a narrow time range of 100 years.)
				datestamp = datestamp[2:]
				ver += "-" + datestamp
				print "Packaged release will be:", ver

			pkgDir = "Webware-%s" % ver

			if os.path.exists(pkgDir):
				self.error("%s is in the way, please remove it." % pkgDir)

			# rename the target to the pkgDir so the extracted parent
			# directory from the tarball will be unique to this package.
			self.run("mv %s %s" % (target, pkgDir))

			cleanup.append(pkgDir)

			pkgName = os.path.join(pkgDir + ".tar.gz")

			# cleanup .cvs files
			self.run("find %s -name '.cvs*' -exec rm {} \;" % pkgDir)

			# We could cleanup any other files not part of this release here.
			# (For instance, we could create releases without documentation).

			# We could also create additional files to be part of this release
			# without being part of the repository, for instance documentation
			# that is automatically created from markup.

			pkgPath = os.path.join(tarDir, pkgName)

			if os.path.exists(pkgPath):
				self.error("%s is in the way, please remove it." % pkgPath)

			self.run('tar -czf %s %s' % (pkgPath, pkgDir))

			if not os.path.exists(pkgPath):
				self.error('Could not create tarball.')

		finally: # Clean up
			for path in cleanup:
				if os.path.exists(path):
					self.run('rm -rf ' + path)

		print
		print "file:", pkgName
		print "dir:", os.path.abspath(tarDir)
		print "size:", os.path.getsize(pkgPath), 'Bytes'
		print
		print 'Success.'
		print
Exemplo n.º 19
0
class PlugIn:
    """Template for Webware Plug-ins.

    A plug-in is a software component that is loaded by Webware in order to
    provide additional Webware functionality without necessarily having to
    modify Webware's source. The most infamous plug-in is PSP (Python Server
    Pages) which ships with Webware.

    Plug-ins often provide additional servlet factories, servlet subclasses,
    examples and documentation. Ultimately, it is the plug-in author's choice
    as to what to provide and in what manner.

    Instances of this class represent plug-ins which are ultimately Python
    packages.

    A plug-in must also be a Webware component which means that it will have
    a Properties.py file advertising its name, version, requirements, etc.
    You can ask a plug-in for its properties().

    The plug-in/package must have an __init__.py which must contain the
    following function::

        def installInWebware(application):
            ...

    This function is invoked to take whatever actions are needed to plug the
    new component into Webware. See PSP for an example.

    If you ask an Application for its plugIns(), you will get a list of
    instances of this class.

    The path of the plug-in is added to sys.path, if it's not already there.
    This is convenient, but we may need a more sophisticated solution in the
    future to avoid name collisions between plug-ins.

    Note that this class is hardly ever subclassed. The software in the
    plug-in package is what provides new functionality and there is currently
    no way to tell the Application to use custom subclasses of this class on a
    case-by-case basis (and so far there is currently no need).

    Instructions for invoking::

        # 'self' is typically Application. It gets passed to installInWebware()
        p = PlugIn(self, 'Foo', '../Foo')
        willNotLoadReason = plugIn.load()
        if willNotLoadReason:
            print(f'Plug-in {path} cannot be loaded because:')
            print(willNotLoadReason)
            return None
        p.install()
        # Note that load() and install() could raise exceptions.
        # You should expect this.
    """

    # region Init, load and install

    def __init__(self, application, name, module):
        """Initializes the plug-in with basic information.

        This lightweight constructor does not access the file system.
        """
        self._app = application
        self._name = name
        self._module = module
        self._path = module.__path__[0]
        try:
            self._builtin = module.__package__ == f'webware.{name}'
        except AttributeError:
            self._builtin = False
        self._dir = os.path.dirname(self._path)
        self._cacheDir = os.path.join(self._app._cacheDir, self._name)
        self._examplePages = self._examplePagesContext = None

    def load(self, verbose=True):
        """Loads the plug-in into memory, but does not yet install it.

        Will return None on success, otherwise a message (string) that says
        why the plug-in could not be loaded.
        """
        if verbose:
            print(f'Loading plug-in: {self._name} at {self._path}')

        # Grab the Properties.py
        self._properties = PropertiesObject(
            self.serverSidePath('Properties.py'))

        if self._builtin and 'version' not in self._properties:
            self._properties['version'] = self._app._webwareVersion
            self._properties['versionString'] = self._app._webwareVersionString

        if not self._properties['willRun']:
            return self._properties['willNotRunReason']

        # Update sys.path
        if self._dir not in sys.path:
            sys.path.append(self._dir)

        # Inspect it and verify some required conventions
        if not hasattr(self._module, 'installInWebware'):
            raise PlugInError(f"Plug-in '{self._name!r}' in {self._dir!r}"
                              " has no installInWebware() function.")

        # Give the module a pointer back to us
        setattr(self._module, 'plugIn', self)

        # Make a subdirectory for it in the Cache directory:
        if not os.path.exists(self._cacheDir):
            os.mkdir(self._cacheDir)

        self.setUpExamplePages()

    def setUpExamplePages(self):
        """Add a context for the examples."""
        if self._app.hasContext('Examples'):
            config = self._properties.get('webwareConfig', {})
            self._examplePages = config.get('examplePages') or None
            if self.hasExamplePages():
                examplesPath = self.serverSidePath('Examples')
                if not os.path.exists(examplesPath):
                    raise PlugInError(
                        f'Plug-in {self._name!r} says it has example pages, '
                        'but there is no Examples/ subdir.')
                if os.path.exists(os.path.join(examplesPath, '__init__.py')):
                    ctxName = self._name + '/Examples'
                    if not self._app.hasContext(ctxName):
                        self._app.addContext(ctxName, examplesPath)
                    self._examplePagesContext = ctxName
                else:
                    raise PlugInError(
                        'Cannot create Examples context for'
                        f' plug-in {self._name!r} (no __init__.py found).')

    def examplePages(self):
        return self._examplePages

    def hasExamplePages(self):
        return self._examplePages is not None

    def examplePagesContext(self):
        return self._examplePagesContext

    def install(self):
        """Install plug-in by invoking its installInWebware() function."""
        self._module.installInWebware(self._app)

    # endregion Init, load and install

    # region Access

    def name(self):
        """Return the name of the plug-in. Example: 'Foo'"""
        return self._name

    def directory(self):
        """Return the directory in which the plug-in resides. Example: '..'"""
        return self._dir

    def path(self):
        """Return the full path of the plug-in. Example: '../Foo'"""
        return self._path

    def serverSidePath(self, path=None):
        if path:
            return os.path.normpath(os.path.join(self._path, path))
        return self._path

    def module(self):
        """Return the Python module object of the plug-in."""
        return self._module

    def properties(self):
        """Return the properties.

        This is a dictionary-like object, of the plug-in which comes
        from its Properties.py file. See MiscUtils.PropertiesObject.py.
        """
        return self._properties
Exemplo n.º 20
0
Arquivo: PlugIn.py Projeto: Cito/w4py
class PlugIn(object):
    """Template for Webware Plug-ins.

    A plug-in is a software component that is loaded by WebKit in order to
    provide additional WebKit functionality without necessarily having to modify
    WebKit's source. The most infamous plug-in is PSP (Python Server Pages)
    which ships with Webware.

    Plug-ins often provide additional servlet factories, servlet subclasses,
    examples and documentation. Ultimately, it is the plug-in author's choice
    as to what to provide and in what manner.

    Instances of this class represent plug-ins which are ultimately Python
    packages (see the Python Tutorial, 6.4: "Packages" at
    http://docs.python.org/tut/node8.html#SECTION008400000000000000000).

    A plug-in must also be a Webware component which means that it will have
    a Properties.py file advertising its name, version, requirements, etc.
    You can ask a plug-in for its properties().

    The plug-in/package must have an __init__.py while must contain a function:
        def InstallInWebKit(appServer):
    This function is invoked to take whatever actions are needed to plug the
    new component into WebKit. See PSP for an example.

    If you ask an AppServer for its plugIns(), you will get a list of instances
    of this class.

    The path of the plug-in is added to sys.path, if it's not already there.
    This is convenient, but we may need a more sophisticated solution in the
    future to avoid name collisions between plug-ins.

    Note that this class is hardly ever subclassed. The software in the
    plug-in package is what provides new functionality and there is currently
    no way to tell AppServer to use custom subclasses of this class on a
    case-by-case basis (and so far there is currently no need).

    Instructions for invoking:
        p = PlugIn(self, '../Foo')  # 'self' is typically AppServer. It gets passed to InstallInWebKit()
        willNotLoadReason = plugIn.load()
        if willNotLoadReason:
            print '    Plug-in %s cannot be loaded because:\n    %s' % (path, willNotLoadReason)
            return None
        p.install()
        # Note that load() and install() could raise exceptions. You should expect this.
    """


    ## Init, load and install ##

    def __init__(self, appServer, path):
        """Initializes the plug-in with basic information.

        This lightweight constructor does not access the file system.
        """
        self._appServer = appServer
        self._path = path
        self._dir, self._name = os.path.split(path)
        self._cacheDir = os.path.join(
            self._appServer.application()._cacheDir, self._name)
        self._ver = '(unknown)'
        self._docs = self._docContext = None
        self._examplePages = self._examplePagesContext = None

    def load(self):
        """Loads the plug-in into memory, but does not yet install it.

        Will return None on success, otherwise a message (string) that says
        why the plug-in could not be loaded.
        """
        print 'Loading plug-in: %s at %s' % (self._name, self._path)

        assert os.path.exists(self._path)

        # Grab the Properties.py
        self._properties = PropertiesObject(self.serverSidePath('Properties.py'))
        if not self._properties['willRun']:
            return self._properties['willNotRunReason']

        # Update sys.path
        if not self._dir in sys.path:
            sys.path.append(self._dir)

        # Import the package
        self._module = __import__(self._name, globals(), [], [])

        # Inspect it and verify some required conventions
        if not hasattr(self._module, 'InstallInWebKit'):
            raise PlugInError(
                "Plug-in '%s' in '%s' has no InstallInWebKit() function."
                % (self._name, self._dir))

        # Give the module a pointer back to us
        setattr(self._module, 'plugIn', self)

        # Make a subdirectory for it in the Cache directory:
        if not os.path.exists(self._cacheDir):
            os.mkdir(self._cacheDir)

        self.setUpDocContext()
        self.setUpExamplePages()

    def setUpDocContext(self):
        """Add a context for the documentation."""
        app = self._appServer.application()
        if app.hasContext('Docs'):
            self._docs = self._properties.get('docs') or None
            if self.hasDocs():
                docsPath = self.serverSidePath('Docs')
                assert os.path.exists(docsPath), (
                    'Plug-in %s says it has documentation, '
                    'but there is no Docs/ subdir.' % self._name)
                if os.path.exists(os.path.join(docsPath, '__init__.py')):
                    ctxName = self._name + '/Docs'
                    if not app.hasContext(ctxName):
                        app.addContext(ctxName, docsPath)
                    self._docContext = ctxName
                else:
                    print ('Cannot create Docs context for plug-in %s'
                        ' (no __init__.py found).' % self._name)

    def setUpExamplePages(self):
        """Add a context for the examples."""
        app = self._appServer.application()
        if app.hasContext('Examples'):
            config = self._properties.get('WebKitConfig', {})
            self._examplePages = config.get('examplePages') or None
            if self.hasExamplePages():
                examplesPath = self.serverSidePath('Examples')
                assert os.path.exists(examplesPath), (
                    'Plug-in %s says it has example pages, '
                    'but there is no Examples/ subdir.' % self._name)
                if os.path.exists(os.path.join(examplesPath, '__init__.py')):
                    ctxName = self._name + '/Examples'
                    if not app.hasContext(ctxName):
                        app.addContext(ctxName, examplesPath)
                    self._examplePagesContext = ctxName
                else:
                    print ('Cannot create Examples context for plug-in %s'
                        ' (no __init__.py found).' % self._name)

    def docs(self):
        return self._docs

    def hasDocs(self):
        return self._docs is not None

    def docsContext(self):
        return self._docsContext

    def examplePages(self):
        return self._examplePages

    def hasExamplePages(self):
        return self._examplePages is not None

    def examplePagesContext(self):
        return self._examplePagesContext

    def install(self):
        """Install plug-in by invoking its required InstallInWebKit function."""
        self._module.InstallInWebKit(self._appServer)


    ## Access ##

    def name(self):
        """Return the name of the plug-in. Example: 'Foo'"""
        return self._name

    def directory(self):
        """Return the directory in which the plug-in resides. Example: '..'"""
        return self._dir

    def path(self):
        """Return the full path of the plug-in. Example: '../Foo'"""
        return self._path

    def serverSidePath(self, path=None):
        if path:
            return os.path.normpath(os.path.join(self._path, path))
        else:
            return self._path

    def module(self):
        """Return the Python module object of the plug-in."""
        return self._module

    def properties(self):
        """Return the properties.

        This is a dictionary-like object, of the plug-in which comes
        from its Properties.py file. See MiscUtils.PropertiesObject.py.
        """
        return self._properties
Exemplo n.º 21
0
	def release_export(self):
		"""
		Prepare a release by using the cvs export approach.  This means the release will
		match exactly what is in CVS, and reduces the risk of local changes, modified
		files, or new files which are not in CVS from showing up in the release.

		Furthermore, this takes the version number from the checked out information.
		This means it is possible to specify a tag=cvstag on the command line and
		build a release associated with that tag.

		    > ReleaseHelper.py [tag=cvstag]

	        So specifying a CVS tag such as Release-0_7 will export the CVS files tagged
		with Release-0_7 and build Webware-0.7.tar.gz
		"""
		
		self.writeHello()
		self.checkPlatform()
		self.readArgs()

		progPath = os.path.join(os.getcwd(), sys.argv[0])  # the location of this script
		webwarePath = os.path.dirname(os.path.dirname(progPath))  # because we're in Webware/bin/
		parentPath = os.path.dirname(webwarePath)  # where the tarball will land
		if webwarePath not in sys.path:
			# insert in the path but ahead of anything that PYTHONPATH might
			# have created.
			sys.path.insert(1,webwarePath)

		self.chdir(webwarePath)
		from MiscUtils.PropertiesObject import PropertiesObject

		if self.args.has_key('tag'):
			dtag = '-r ' + self.args['tag']
			datestamp = ''
		else:
			# timestamp for tomorrow to insure we get latest data off
			# of the trunk.  Is this needed?
			year,month,day = time.gmtime(time.time()+3600*24)[:3]  
			dtag = '-D %04d-%02d-%02d' % (year,month,day)

			# timestamp for time of release used to in versioning the file.
			year,month,day = time.localtime(time.time())[:3]  
			datestamp = "%04d%02d%02d" % (year,month,day)

			# drop leading 2 digits from year. (Ok, itn's not Y2K but it is short
			# and unique in a narrow time range of 100 years.)
			datestamp = datestamp[2:]
			
			print "No cvs tag specified, assuming snapshot of CVS."
			
		tempName = "ReleaseHelper-Export"
		if os.path.exists( tempName ):
			print "There is incomplete ReleaseHelper data in:", tempName
			print "Please remove this directory."
			return 1
		
		cleanup = [ tempName ]
		
		try:
			self.run('cvs -z3 export %s -d %s Webware' % (dtag, tempName))
			if not os.path.exists( tempName ):
				print "** Unable to find the exported package.  Perhaps the tag %s does not exist." % \
				      self.args['tag']
				return 1
			props = PropertiesObject(os.path.join(webwarePath, tempName, 'Properties.py'))
			ver = props['versionString']

			print "Webware version is:", ver
			if datestamp:
				ver = ver + "-" + datestamp
				print "Packaged release will be:", ver

			pkgDir = "Webware-%s" % ver
			
			if os.path.exists(pkgDir):
				print "** %s is in the way, please remove it." % pkgDir
				return

			# rename the tempName to the pkgDir so the extracted parent
			# directory from the tarball will be unique to this package.
			self.run("mv %s %s" % (tempName, pkgDir))
			
			cleanup.append( pkgDir )
			
			pkgName = os.path.join(parentPath, pkgDir + ".tar.gz")

			# cleanup .cvs files
			self.run("find %s -name '.cvs*' -exec rm {} \;" % pkgDir)

			# cleanup any other files not part of this release. (ie: documentation?)

			# build any internal documentation for release.
			
			self.run('tar czf %s %s' % (pkgName, pkgDir))

			assert os.path.exists(os.path.join(parentPath, pkgName))

		finally:
			# Clean up
			for path in cleanup:
				if os.path.exists(path):
					self.run('rm -rf %s' % os.path.join(webwarePath, path))
			 
		self.writeGoodBye(locals())
Exemplo n.º 22
0
 def __init__(self):
     self._props = PropertiesObject('Properties.py')
     self._htHeader = self.htFragment('Header')
     self._htFooter = self.htFragment('Footer')
     self._comps = []
Exemplo n.º 23
0
class PlugIn(Object):
    """
	A plug-in is a software component that is loaded by WebKit in order to provide additional WebKit functionality without necessarily having to modify WebKit's source.
	The most infamous plug-in is PSP (Python Server Pages) which ships with Webware.
	Plug-ins often provide additional servlet factories, servlet subclasses, examples and documentation. Ultimately, it is the plug-in author's choice as to what to provide and in what manner.
	Instances of this class represent plug-ins which are ultimately Python packages (see the Python Tutorial, 6.4: "Packages" at http://www.python.org/doc/current/tut/node8.html#SECTION008400000000000000000).
	A plug-in must also be a Webware component which at means that it will have a Properties.py file advertising its name, version, requirements, etc. You can ask a plug-in for its properties().
	The plug-in/package must have an __init__.py while must contain a function:
		def InstallInWebKit(appServer):
	This function is invoked to take whatever actions are needed to plug the new component into WebKit. See PSP for an example.
	If you ask an AppServer for its plugIns(), you will get a list of instances of this class.
	The path of the plug-in is added to sys.path, if it's not already there. This is convenient, but we may need a more sophisticated solution in the future to avoid name collisions between plug-ins.
	Note that this class is hardly ever subclassed. The software in the plug-in package is what provides new functionality and there is currently no way to tell AppServer to use custom subclasses of this class on a case-by-case basis (and so far there is currently no need).

	Instructions for invoking:
		p = PlugIn(self, '../Foo')   # 'self' is typically AppServer. It gets passed to InstallInWebKit()
		willNotLoadReason = plugIn.load()
		if willNotLoadReason:
			print '    Plug-in %s cannot be loaded because:\n    %s' % (path, willNotLoadReason)
			return None
		p.install()
		# Note that load() and install() could raise exceptions. You should expect this.
	"""

    ## Init, load and install ##

    def __init__(self, appServer, path):
        """ Initializes the plug-in with basic information. This lightweight constructor does not access the file system. """
        self._appServer = appServer
        self._path = path
        self._dir, self._name = os.path.split(path)
        self._ver = '(unknown)'
        self._examplePages = None

    def load(self):
        """ Loads the plug-in into memory, but does not yet install it. Will return None on success, otherwise a message (string) that says why the plug-in could not be loaded. """
        print 'Loading plug-in: %s at %s' % (self._name, self._path)

        assert os.path.exists(self._path)

        # Grab the Properties.py
        self._properties = PropertiesObject(
            self.serverSidePath('Properties.py'))
        if not self._properties['willRun']:
            return self._properties['willNotRunReason']

        # Update sys.path
        if not self._dir in sys.path:
            sys.path.append(self._dir)

        # Import the package
        self._module = __import__(self._name, globals(), [], [])

        # Inspect it and verify some required conventions
        if not hasattr(self._module, 'InstallInWebKit'):
            raise PlugInError, "Plug-in '%s' in '%s' has no InstallInWebKit() function." % (
                self._name, self._dir)

        # Give the module a pointer back to us
        setattr(self._module, 'plugIn', self)

        # Make a directory for it in Cache/
        cacheDir = os.path.join(self._appServer.serverSidePath(), 'Cache',
                                self._name)
        if not os.path.exists(cacheDir):
            os.mkdir(cacheDir)

        self.setUpExamplePages()

    def setUpExamplePages(self):
        # Add a context for the examples
        app = self._appServer.application()
        if app.hasContext('Examples'):
            config = self._properties.get('WebKitConfig', {})
            self._examplePages = config.get('examplePages', None)
            if self._examplePages is not None:
                examplesPath = self.serverSidePath('Examples')
                assert os.path.exists(
                    examplesPath
                ), 'Plug-in %s says it has example pages, but there is no Examples/ subdir.' % self._name
                ctxName = self._name + 'Examples'
                if not app.hasContext(ctxName):
                    app.addContext(ctxName, examplesPath)
                self._examplePagesContext = ctxName

    def hasExamplePages(self):
        return self._examplePages is not None

    def examplePagesContext(self):
        return self._examplePagesContext

    def examplePages(self):
        return self._examplePages

    def install(self):
        """ Installs the plug-in by invoking it's required InstallInWebKit() function. """
        self._module.InstallInWebKit(self._appServer)

    ## Access ##

    def name(self):
        """ Returns the name of the plug-in. Example: 'Foo' """
        return self._name

    def directory(self):
        """ Returns the directory in which the plug-in resides. Example: '..' """
        return self._dir

    def path(self):
        """ Returns the full path of the plug-in. Example: '../Foo' """
        return self._path

    def serverSidePath(self, path=None):
        if path:
            return os.path.normpath(os.path.join(self._path, path))
        else:
            return self._path

    def module(self):
        """ Returns the Python module object of the plug-in. """
        return self._module

    def properties(self):
        """ Returns the properties, a dictionary-like object, of the plug-in which comes from its Properties.py file. See MiscUtils.PropertiesObject.py. """
        return self._properties

    ## Deprecated ##

    def version(self):
        """
		DEPRECATED: PlugIn.version() on 1/25 in ver 0.5. Use self.properties()['versionString'] instead. @
		Returns the version of the plug-in as reported in its Properties.py. Example: (0, 2, 0)
		"""
        self.deprecated(self.version)
        return self._properties['version']
Exemplo n.º 24
0
class Installer:
	"""Install Webware.

	The _comps attribute is a list of components,
	each of which is an instance of MiscUtils.PropertiesObject.

	"""


	## Init ##

	def __init__(self):
		self._props = PropertiesObject('Properties.py')
		self._props['dirname'] = '.'
		self._comps = []
		self._htHeader, self._htFooter = self.htHeaderAndFooter()
		from DocSupport.pytp import PyTP
		self._pytp = PyTP()
		from DocSupport.autotoc import AutoToC
		self._autotoc = AutoToC()


	## Debug printing facility ##

	def _nop (self, msg):
		pass

	def _printMsg (self, msg):
		print '  ' + msg


	## Running the installation ##

	def run(self, verbose=0, passprompt=1, defaultpass='', keepdocs=0):
		self._verbose = verbose
		self.printMsg = verbose and self._printMsg or self._nop
		log = []
		stdout, stderr = sys.stdout, sys.stderr
		try:
			sys.stdout = OutputCatcher(sys.stdout, log)
			sys.stderr = OutputCatcher(sys.stderr, log)
			self.printHello()
			self.clearLogFile()
			if not self.checkPyVersion() or not self.checkThreading():
				return
			self.detectComponents()
			self.installDocs(keepdocs)
			self.backupConfigs()
			self.copyStartScript()
			self.compileModules()
			self.fixPermissions()
			self.setupWebKitPassword(passprompt, defaultpass)
			self.printGoodbye()
			self.writeLogFile(log)
		finally:
			sys.stdout, sys.stderr = stdout, stderr

	def clearLogFile(self):
		"""Remove the install.log file.

		This file with the logged output will get created at the
		very end of the installation, provided there are no errors.
		"""
		if os.path.exists('install.log'):
			print 'Removing log from last installation...'
			os.remove('install.log')
			print

	def printHello(self):
		from time import time, localtime, asctime
		print '%(name)s %(versionString)s' % self._props
		print 'Installer'
		print
		self.printKeyValue('Cur Date', asctime(localtime(time())))
		self.printKeyValue('Python', sys.version.replace(') [', ')\n['))
		self.printKeyValue('Op Sys', os.name)
		self.printKeyValue('Platform', sys.platform)
		self.printKeyValue('Cur Dir', os.getcwd())
		print

	def checkPyVersion(self, minver=(2, 0)):
		"""Check for minimum required Python version."""
		try:
			ver = sys.version_info[:len(minver)]
		except AttributeError:
			ver = (1,)
		if ver < minver:
			print ('This Release of Webware requires Python %s.\n'
				'Your currently used version is Python %s.\n'
				'You can download a newer version at: http://www.python.org\n'
				% ('.'.join(map(str, minver)), '.'.join(map(str, ver))))
			response = raw_input('You may continue to install, '
				'but Webware may not perform as expected.\n'
				'Do you wish to continue with the installation?  [yes/no] ')
			return response[:1].upper() == "Y"
		return 1

	def checkThreading(self):
		try:
			import threading
		except ImportError:
			print ('Webware requires that Python be compiled with threading support.\n'
				'This version of Python does not appear to support threading.\n')
			response = raw_input('You may continue, '
				'but you will have to run the AppServer with a Python\n'
				'interpreter that has threading enabled.\n'
				'Do you wish to continue with the installation? [yes/no] ')
			return response[:1].upper() == "Y"
		return 1

	def detectComponents(self):
		print 'Scanning for components...'
		dirNames = filter(lambda dir: not dir.startswith('.')
				and os.path.isdir(dir), os.listdir(os.curdir))
		dirNames.sort()
		self._maxCompLen = max(map(len, dirNames))
		oldPyVersion = 0
		column = 0
		for dirName in dirNames:
			propName = dirName + '/Properties.py'
			try:
				print dirName.ljust(self._maxCompLen, '.'),
			except TypeError:
				print dirName.ljust(self._maxCompLen),
			if os.path.exists(propName):
				comp = PropertiesObject(propName)
				comp['dirname'] = dirName
				for key in self._props.keys():
					if not comp.has_key(key):
						comp[key] = self._props[key]
				if sys.version_info[:3] < comp['requiredPyVersion']:
					oldPyVersion += 1
					print 'no*',
				else:
					self._comps.append(comp)
					print 'yes',
			else:
				print 'no ',
			if column < 2 and not self._verbose:
				print '   ',
				column += 1
			else:
				print
				column = 0
		if column:
			print
		if oldPyVersion:
			print "* some components require a newer Python version"
		self._comps.sort(lambda a, b: cmp(a['name'], b['name']))
		print

	def setupWebKitPassword(self, prompt, defpass):
		"""Setup a password for WebKit Application server."""
		print 'Setting the WebKit password...'
		print
		if prompt:
			print 'Choose a password for the WebKit Application Server.'
			print 'If you will just press enter without entering anything,'
			if defpass is None:
				print 'a password will be automatically generated.'
			else:
				print 'the password specified on the command-line will be used.'
			from getpass import getpass
			password = getpass()
		else:
			if defpass is None:
				print 'A password will be automatically generated.'
			else:
				print 'A password was specified on the command-line.'
			password = None
		print 'You can check the password after installation at:'
		appConfig = 'WebKit/Configs/Application.config'
		print os.path.normpath(appConfig)
		if not password:
			if defpass is None:
				from string import letters, digits
				from random import choice
				password = ''.join(map(choice, [letters + digits]*8))
			else:
				password = defpass
		try: # read config file
			data = open(appConfig).read()
		except IOError:
			print 'Error reading Application.config file.'
			print 'Password not replaced, make sure to edit it by hand.'
			print
			return
		# This will search for the construct "'AdminPassword': '******'"
		# and replace '...' with the content of the 'password' variable:
		if data.lstrip().startswith('{'):
			pattern = "('AdminPassword'\s*:)\s*'.*?'"
		else: # keyword arguments style
			pattern = "(AdminPassword\\s*=)\\s*['\"].*?['\"]"
		repl = "\g<1> '%s'" % password.replace( # escape critical characters
			'\\', '\\\\\\\\').replace("'", "\\\\'").replace('%', '\\\\045')
		from re import subn
		data, count = subn(pattern, repl, data)
		if count != 1:
			print "Warning:",
			if count > 1:
				print "More than one 'AdminPassword' in config file."
			else:
				print "'AdminPassword' not found in config file."
			return
		try: # write back config file
			open(appConfig, 'w').write(data)
		except IOError:
			print 'Error writing Application.config (probably no permission).'
			print 'Password not replaced, make sure to edit it by hand.'
			print
			return
		print 'Password replaced successfully.'
		print

	def installDocs(self, keep):
		self.processHtmlDocFiles()
		self.processPyTemplateFiles(keep)
		self.createBrowsableSource()
		self.createComponentIndex()
		self.createComponentIndexes(keep)
		self.createDocContexts()

	def processHtmlDocFiles(self):
		print 'Processing html doc files...'
		for htmlFile in glob('Docs/*.html'):
			self.processHtmlDocFile(htmlFile)
		for comp in self._comps:
			dir = comp['dirname']
			for htmlFile in glob(dir + '/Docs/*.html'):
				self.processHtmlDocFile(htmlFile)
		print

	def processPyTemplateFiles(self, keep):
		print 'Processing phtml doc files...'
		if keep:
			print 'The templates will not be removed.'
		else:
			print 'The templates will be removed afterwards.'
		for inFile in glob('Docs/*.phtml'):
			if not os.path.splitext(inFile)[0].endswith('OfComponent'):
				self.processPyTemplateFile(inFile, self._props, keep)
		for comp in self._comps:
			dir = comp['dirname']
			for inFile in glob(dir + '/Docs/*.phtml'):
				self.processPyTemplateFile(inFile, comp, keep)
		print

	def createBrowsableSource(self):
		"""Create HTML docs for class hierarchies, summaries, sources etc."""
		print 'Creating html source, summaries and doc files...'
		column = 0
		for comp in self._comps:
			dir = comp['dirname']
			if self._verbose:
				print dir, '...'
			else:
				try:
					print dir.ljust(self._maxCompLen, '.'),
				except TypeError:
					print dir.ljust(self._maxCompLen),
			sourceDir = dir + '/Docs/Source'
			self.makeDir(sourceDir)
			filesDir = sourceDir + '/Files'
			self.makeDir(filesDir)
			summariesDir = sourceDir + '/Summaries'
			self.makeDir(summariesDir)
			docsDir = sourceDir + '/Docs'
			self.makeDir(docsDir)
			for pyFilename in glob(dir + '/*.py'):
				self.createHighlightedSource(pyFilename, filesDir)
				self.createPySummary(pyFilename, summariesDir)
				self.createPyDocs(pyFilename, docsDir)
			self.createPyDocs(dir, docsDir)
			self.createFileList(dir, sourceDir)
			self.createClassList(dir, sourceDir)
			if not self._verbose:
				print "ok",
				if column < 2:
					print '    ',
					column += 1
				else:
					print
					column = 0
		if column:
			print
		print

	def createHighlightedSource(self, filename, dir):
		"""Create highlighted HTML source code using py2html."""
		from DocSupport import py2html
		module = os.path.splitext(os.path.basename(filename))[0]
		targetName = '%s/%s.html' % (dir, module)
		self.printMsg('Creating %s...' % targetName)
		stdout = sys.stdout
		try:
			sys.stdout = StringIO()
			py2html.main((None, '-stdout', '-files', filename))
			result = sys.stdout.getvalue()
		finally:
			sys.stdout = stdout
		open(targetName, 'w').write(result)

	def createPySummary(self, filename, dir):
		"""Create a HTML module summary."""
		from DocSupport.PySummary import PySummary
		module = os.path.splitext(os.path.basename(filename))[0]
		targetName = '%s/%s.html' % (dir, module)
		self.printMsg('Creating %s...' % targetName)
		sum = PySummary()
		sum.readConfig('DocSupport/PySummary.config')
		sum.readFileNamed(filename)
		html = sum.html()
		open(targetName, 'w').write(html)

	def createPyDocs(self, filename, dir):
		"""Create a HTML module documentation using pydoc."""
		try:
			import pydoc
		except ImportError:
			from MiscUtils import pydoc
		package, module = os.path.split(filename)
		module = os.path.splitext(module)[0]
		if package:
			module = package + '.' + module
		targetName = '%s/%s.html' % (dir, module)
		self.printMsg('Creating %s...' % targetName)
		saveDir = os.getcwd()
		try:
			os.chdir(dir)
			targetName = '../' + targetName
			stdout = sys.stdout
			sys.stdout = StringIO()
			try:
				pydoc.writedoc(module)
			except Exception:
				pass
			msg = sys.stdout.getvalue()
			sys.stdout = stdout
			if msg:
				self.printMsg(msg)
		finally:
			os.chdir(saveDir)

	def createFileList(self, filesDir, docsDir):
		"""Create a HTML list of the source files."""
		from DocSupport.FileList import FileList
		name = os.path.basename(filesDir)
		self.printMsg('Creating file list of %s...' % name)
		filelist = FileList(name)
		saveDir = os.getcwd()
		os.chdir(filesDir)
		try:
			filelist.readFiles('*.py')
			targetName = '../' + docsDir + '/FileList.html'
			self.printMsg('Creating %s...' % targetName)
			filelist.printForWeb(targetName)
		finally:
			os.chdir(saveDir)

	def createClassList(self, filesDir, docsDir):
		"""Create a HTML class hierarchy listing of the source files."""
		from DocSupport.ClassList import ClassList
		name = os.path.basename(filesDir)
		self.printMsg('Creating class list of %s...' % name)
		classlist = ClassList(name)
		saveDir = os.getcwd()
		os.chdir(filesDir)
		try:
			classlist.readFiles('*.py')
			targetName = '../' + docsDir + '/ClassList.html'
			self.printMsg('Creating %s...' % targetName)
			classlist.printForWeb(0, targetName)
			targetName = '../' + docsDir + '/ClassHierarchy.html'
			self.printMsg('Creating %s...' % targetName)
			classlist.printForWeb(1, targetName)
		finally:
			os.chdir(saveDir)

	def createComponentIndex(self):
		"""Create a HTML component index of Webware itself."""
		print 'Creating ComponentIndex.html...'
		ht = ["<% header('Webware Documentation', 'titlebar',"
			" 'ComponentIndex.css') %>"]
		wr = ht.append
		wr('<p>Don\'t know where to start? '
			'Try <a href="../WebKit/Docs/index.html">WebKit</a>.</p>')
		wr('<table align="center" border="0" '
			'cellpadding="2" cellspacing="2" width="100%">')
		wr('<tr class="ComponentHeadings">'
			'<th>Component</th><th>Status</th><th>Ver</th>'
			'<th>Py</th><th>Summary</th></tr>')
		row = 0
		for comp in self._comps:
			comp['nameAsLink'] = ('<a href='
				'"../%(dirname)s/Docs/index.html">%(name)s</a>' % comp)
			comp['indexRow'] = row + 1
			wr('<tr valign="top" class="ComponentRow%(indexRow)i">'
				'<td class="NameVersionCell">'
				'<span class="Name">%(nameAsLink)s</span></td>'
				'<td>%(status)s</td>'
				'<td><span class="Version">%(versionString)s</span></td>'
				'<td>%(requiredPyVersionString)s</td>'
				'<td>%(synopsis)s</td></tr>' % comp)
			row = 1 - row
		wr('</table>')
		wr("<% footer() %>")
		ht = '\n'.join(ht)
		ht = self.processPyTemplate(ht, self._props)
		open('Docs/ComponentIndex.html', 'w').write(ht)

	def createComponentIndexes(self, keep):
		"""Create start page for all components."""
		indexfile = 'Docs/indexOfComponent.phtml'
		if not os.path.exists(indexfile):
			return
		print "Creating index.html for all components..."
		index = open(indexfile).read()
		link = '<p><a href="%s">%s</a></p>'
		for comp in self._comps:
			comp['webwareVersion'] = self._props['version']
			comp['webwareVersionString'] = self._props['versionString']
			# Create 'htDocs' as a HTML fragment corresponding to comp['docs']
			ht = []
			for doc in comp['docs']:
				ht.append(link % (doc['file'], doc['name']))
			ht = ''.join(ht)
			comp['htDocs'] = ht
			# Set up release notes
			ht = []
			files = glob(comp['dirname'] + '/Docs/RelNotes-*.html')
			if files:
				releaseNotes = []
				for filename in files:
					item = {'dirname': os.path.basename(filename)}
					filename = item['dirname']
					ver = filename[
						filename.rfind('-') + 1 : filename.rfind('.')]
					item['name'] = ver
					if ver == 'X.Y':
						item['ver'] = ver.split('.')
					else:
						i = 0
						while i < len(ver) and ver[i] in '.0123456789':
							i += 1
						if i:
							item['ver'] = map(int, ver[:i].split('.'))
					releaseNotes.append(item)
				releaseNotes.sort(lambda a, b: cmp(b['ver'], a['ver']))
				for item in releaseNotes:
					ht.append(link % (item['dirname'], item['name']))
			else:
				ht.append('<p>None</p>')
			ht = '\n'.join(ht)
			comp['htReleaseNotes'] = ht
			# Write file
			filename = comp['dirname'] + '/Docs/index.html'
			ht = self.processPyTemplate(index, comp)
			open(filename, 'w').write(ht)
		if not keep:
			os.remove(indexfile)
		print

	def createDocContexts(self):
		"""Create a WebKit context for every Docs directory."""
		print 'Making all Docs directories browsable via WebKit...'
		# Place an __init__.py file in every Docs directory
		docsDirs = ['Docs']
		for comp in self._comps:
			if comp.get('docs', None):
				docsDir = comp['dirname'] + '/Docs'
				if os.path.isdir(docsDir):
					docsDirs.append(docsDir)
		for docsDir in docsDirs:
			initFile = docsDir + '/__init__.py'
			if not os.path.exists(initFile) or 1:
				open(initFile, 'w').write(
					'# this can be browsed as a Webware context\n')
		# Copy favicon to the default context
		open('WebKit/Examples/favicon.ico', 'wb').write(
			open('Docs/favicon.ico', 'rb').read())
		print

	def backupConfigs(self):
		"""Copy *.config to *.config.default, if they don't already exist.

		This allows the user to always go back to the default config file if
		needed (for troubleshooting for example).

		"""
		print 'Creating backups of original config files...'
		self._backupConfigs(os.curdir)
		print

	def _backupConfigs(self, dir):
		for filename in os.listdir(dir):
			fullPath = os.path.join(dir, filename)
			if os.path.isdir(fullPath):
				self._backupConfigs(fullPath)
			elif (not filename.startswith('.') and
				os.path.splitext(filename)[1] == '.config'):
				self.printMsg(fullPath)
				backupPath = fullPath + '.default'
				if not os.path.exists(backupPath):
					open(backupPath, 'wb').write(open(fullPath, 'rb').read())

	def copyStartScript(self):
		"""Copy the most appropriate start script to WebKit/webkit."""
		if os.name == 'posix':
			print 'Copying start script...',
			ex = os.path.exists
			if ex('/etc/rc.status') and \
				ex('/sbin/startproc') and \
				ex('/sbin/killproc'):
				s = 'SuSE'
			elif ex('/etc/init.d/functions') or \
				ex('/etc/rc.d/init.d/functions'):
				s = 'RedHat'
			elif ex('/sbin/start-stop-daemon'):
				s = 'Debian'
			elif ex('/etc/rc.subr'):
				s = 'NetBSD'
			else:
				s = 'Generic'
			print s
			# Copy start script:
			s = 'WebKit/StartScripts/' + s
			t = 'WebKit/webkit'
			open(t, 'wb').write(open(s, 'rb').read())
			print

	def compileModules(self, force=0):
		"""Compile modules in all installed componentes."""
		from compileall import compile_dir
		print 'Byte compiling all modules...'
		for comp in self._comps:
			dir = comp['dirname']
			try:
				compile_dir(dir, force=force, quiet=1)
			except TypeError: # workaround for Python < 2.3
				stdout = sys.stdout
				sys.stdout = StringIO()
				compile_dir(dir, force=force)
				sys.stdout = stdout
		print

	def fixPermissions(self):
		if os.name == 'posix':
			print 'Setting permissions on CGI scripts...'
			for comp in self._comps:
				for filename in glob(comp['dirname'] + '/*.cgi'):
					cmd = 'chmod a+rx ' + filename
					self.printMsg(cmd)
					os.system(cmd)
			print 'Setting permission on start script...'
			cmd = 'chmod a+rx WebKit/webkit'
			self.printMsg(cmd)
			os.system(cmd)
			print

	def printGoodbye(self):
		print '''
Installation looks successful.

Welcome to Webware!

You can already try out the WebKit application server. Start it with
"WebKit%sAppServer" and point your browser to "http://localhost:8080".

Browsable documentation is available in the Docs folders.
You can use "Docs%sindex.html" as the main entry point.

Installation is finished.''' % ((os.sep,)*2)

	def writeLogFile(self, log):
		"""Write the logged output to the install.log file."""
		open('install.log', 'w').write(''.join(log))


	## Self utility ##

	def printKeyValue(self, key, value):
		"""Print a key/value pair."""
		value = value.split('\n')
		v = value.pop(0)
		print '%12s: %s' % (key, v)
		for v in value:
			print '%14s%s' % ('', v)

	def makeDir(self, dirName):
		"""Create a directory."""
		if not os.path.exists(dirName):
			self.printMsg('Making %s...' % dirName)
			os.makedirs(dirName)

	def htHeaderAndFooter(self):
		"""Return header and footer from HTML template."""
		template = open('Docs/Template.html').read()
		return template.split('\n<!-- page content -->\n', 1)

	def processHtmlDocFile(self, htmlFile):
		"""Process a HTML file."""
		txtFile = os.path.splitext(htmlFile)[0] + '.txt'
		if os.path.exists(txtFile):
			# A text file with the same name exists:
			page = open(htmlFile).read()
			if page.find('<meta name="generator" content="Docutils') > 0 \
				and page.find('<h1 class="title">') > 0:
				# This has obvisouly been created with Docutils; modify it
				# to match style, header and footer of all the other docs.
				page = page.replace('<h1 class="title">',
					'<h1 class="header">')
				page = page.replace('</body>\n</html>', self._htFooter)
				self.printMsg('Modifying %s...' % htmlFile)
				open(htmlFile, 'w').write(page)

	def processPyTemplateFile(self, inFile, props, keep):
		"""Process a Python template file."""
		page = open(inFile).read()
		page = self.processPyTemplate(page, props)
		outFile = os.path.splitext(inFile)[0] + '.html'
		self.printMsg('Creating %s...' % outFile)
		open(outFile, 'w').write(page)
		if not keep:
			os.remove(inFile) # remove template

	def processPyTemplate(self, input, props):
		"""Process a Python template."""
		global scope

		def header(title, titleclass=None, style=None):
			"""Get the header of a document."""
			if not titleclass:
				titleclass = 'header'
			titleclass = ' class="%s"' % titleclass
			link = '<link rel="stylesheet" href="%s" type="text/css">'
			stylesheets = ['Doc.css']
			if style and style.endswith('.css'):
				stylesheets.append(style)
				style = None
			css = []
			for s in stylesheets:
				if not scope['dirname'].startswith('.'):
					s = '../../Docs/' + s
				s = link % s
				css.append(s)
			if style:
				css.extend(('<style type="text/css">',
					'<!--', style, '-->', '</style>'))
			css = '\n'.join(css)
			return scope['htHeader'] % locals()

		def footer():
			"""Get the footer of a document."""
			return scope['htFooter']

		scope = props.copy()
		try:
			scope = dict(props)
		except NameError: # workaround for Python < 2.2
			scope = {}
			for k in props.keys():
				scope[k] = props[k]
		scope.update({'header': header, 'htHeader': self._htHeader,
				'footer': footer, 'htFooter': self._htFooter})
		return self._autotoc.process(self._pytp.process(input, scope))