#!/usr/bin/python2.4.4 # Imports ---------------------------------------------------------------------- import os, os.path, shutil, re, zipfile, sys, ftplib, time from appy.shared import appyPath from appy.shared.utils import FolderDeleter from appy.bin.clean import Cleaner from appy.gen.utils import produceNiceMessage # ------------------------------------------------------------------------------ versionRex = re.compile('(\d+\.\d+\.\d+)') eggInfo = '''import os, setuptools setuptools.setup( name = "appy", version = "%s", description = "The Appy framework", long_description = "See http://appyframework.org", author = "Gaetan Delannay", author_email = "gaetan.delannay AT gmail.com", license = "GPL", keywords = "plone, pod, pdf, odt, document", url = 'http://appyframework.org', classifiers = ['Development Status :: 4 - Beta', "License :: OSI Approved"], packages = setuptools.find_packages('src'), include_package_data = True, package_dir = {'':'src'}, data_files = [('.', [])], namespace_packages = ['appy'], zip_safe = False)''' def askLogin(): print 'Login: ', login = sys.stdin.readline().strip() print 'Password: ', passwd = sys.stdin.readline().strip() return (login, passwd) def askQuestion(question, default='yes'): '''Asks a question to the user (yes/no) and returns True if the user answered "yes".''' defaultIsYes = (default.lower() in ('y', 'yes')) if defaultIsYes: yesNo = '[Y/n]' else: yesNo = '[y/N]' print question + ' ' + yesNo + ' ', response = sys.stdin.readline().strip().lower() res = False if response in ('y', 'yes'): res = True elif response in ('n', 'no'): res = False elif not response: # It depends on default value if defaultIsYes: res = True else: res = False return res class FtpFolder: '''Represents a folder on a FTP site.''' def __init__(self, name): self.name = name self.parent = None self.subFolders = [] self.files = [] self.isComplete = False # Is True if all contained files and direct # subFolders were analysed. def getFullName(self): if not self.parent: res = '.' else: res = '%s/%s' % (self.parent.getFullName(), self.name) return res def addSubFolder(self, subFolder): self.subFolders.append(subFolder) subFolder.parent = self def isFullyComplete(self): res = self.isComplete for subFolder in self.subFolders: res = res and subFolder.isFullyComplete() return res def getIncompleteSubFolders(self): res = [] for subFolder in self.subFolders: if not subFolder.isComplete: res.append(subFolder) elif not subFolder.isFullyComplete(): res += subFolder.getIncompleteSubFolders() return res def __str__(self): res = 'Folder %s' % self.getFullName() if self.files: res += '\nFiles:\n' for f in self.files: res += '%s\n' % f if self.subFolders: res += '\nSubFolders:\n' for subFolder in self.subFolders: res += str(subFolder) return res def clean(self, site): '''Cleans this folder''' # First, clean subFolders if they exist for subFolder in self.subFolders: subFolder.clean(site) # Remove the subFolder site.rmd(subFolder.getFullName()) # Then, remove the files contained in the folder. for f in self.files: fileName = '%s/%s' % (self.getFullName(), f) site.delete(fileName) # ------------------------------------------------------------------------------ class AppySite: '''Represents the Appy web sie where the project is published.''' name = 'appyframework.org' textExtensions = ('.htm', '.html', '.css', '.txt') def __init__(self): # Delete the "egg" folder on not-yet-copied local site. eggFolder = '%s/temp/egg' % appyPath if os.path.isdir(eggFolder): FolderDeleter.delete(eggFolder) # Ask user id and password for FTP transfer userId, userPassword = askLogin() self.site = ftplib.FTP(self.name) self.site.login(userId, userPassword) self.rootFolder = None # Root folder of appy site ~FtpFolder~ self.currentFolder = None # Currently visited folder ~FtpFolder~ def analyseFolderEntry(self, folderEntry): '''p_line corresponds to a 'ls' entry.''' elems = folderEntry.split(' ') elemName = elems[len(elems)-1] if (not elemName.startswith('.')) and \ (not elemName.startswith('_')): if elems[0].startswith('d'): self.currentFolder.addSubFolder(FtpFolder(elemName)) else: self.currentFolder.files.append(elemName) def createFolderProxies(self): '''Creates a representation of the FTP folders of the appy site in the form of FtpFolder instances.''' self.rootFolder = FtpFolder('.') self.currentFolder = self.rootFolder self.site.dir(self.currentFolder.getFullName(), self.analyseFolderEntry) self.rootFolder.isComplete = True while not self.rootFolder.isFullyComplete(): incompleteFolders = self.rootFolder.getIncompleteSubFolders() for folder in incompleteFolders: self.currentFolder = folder self.site.dir(self.currentFolder.getFullName(), self.analyseFolderEntry) self.currentFolder.isComplete = True def copyFile(self, fileName): '''Copies a file on the FTP server.''' localFile = file(fileName) cmd = 'STOR %s' % fileName fileExt = os.path.splitext(fileName)[1] if fileExt in self.textExtensions: # Make a transfer in text mode print 'Transfer file %s (text mode)' % fileName self.site.storlines(cmd, localFile) else: # Make a transfer in binary mode print 'Transfer file %s (binary mode)' % fileName self.site.storbinary(cmd, localFile) def publish(self): # Delete the existing content of the distant site self.createFolderProxies() print 'Removing existing data on site...' self.rootFolder.clean(self.site) curDir = os.getcwd() os.chdir('%s/temp' % appyPath) for root, dirs, files in os.walk('.'): for folder in dirs: folderName = '%s/%s' % (root, folder) self.site.mkd(folderName) for f in files: fileName = '%s/%s' % (root, f) self.copyFile(fileName) os.chdir(curDir) self.site.close() # ------------------------------------------------------------------------------ class Text2Html: '''Converts a text file into a HTML file.''' def __init__(self, txtFile, htmlFile): self.txtFile = file(txtFile) self.htmlFile = file(htmlFile, 'w') def retainLine(self, line): '''Must we dump this line in the result ?''' pass def getFirstChar(self, line): '''Gets the first relevant character of the line. For a TodoConverter this is not really the first one because lines taken into account start with a 'v' character.''' return line[self.firstChar] def getCleanLine(self, line, isTitle=False): '''Gets the line as it will be inserted in the HTML result: remove some leading and trailing characters.''' start = self.firstChar if not isTitle: start += 1 return line[start:-1] def getProlog(self): '''If you want to write a small prolog in the HTML file, you may generate it here.''' return '' def run(self): self.htmlFile.write('\n\n