#!/usr/bin/python # Imports ---------------------------------------------------------------------- import os, os.path, sys, shutil, re, zipfile, sys, ftplib, time import appy from appy.shared import appyPath from appy.shared.utils import FolderDeleter, LinesCounter from appy.shared.packaging import Debianizer from appy.bin.clean import Cleaner from appy.gen.utils import produceNiceMessage # ------------------------------------------------------------------------------ versionRex = re.compile('(\d+\.\d+\.\d+)') distInfo = '''from distutils.core import setup setup(name = "appy", version = "%s", description = "The Appy framework", long_description = "Appy builds simple but complex web Python apps.", author = "Gaetan Delannay", author_email = "gaetan.delannay AT geezteem.com", license = "GPL", platforms="all", url = 'http://appyframework.org', packages = [%s], package_data = {'':["*.*"]}) ''' manifestInfo = ''' recursive-include appy/bin * recursive-include appy/fields * recursive-include appy/gen * recursive-include appy/pod * recursive-include appy/shared * ''' def askLogin(): print('Login:') login = sys.stdin.readline().strip() print('Password:') passwd = sys.stdin.readline().strip() return (login, passwd) 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 print(('Cleaning %s %d subFolders' % \ (self.getFullName(), len(self.subFolders)))) 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) print(('%s removed.' % 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 (elemName.startswith('.') or elemName.startswith('_')) and \ (not elemName.startswith('__init__.py')): return 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