git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@36607 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			550 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			550 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #----------------------------------------------------------------------------
 | |
| # Name:         project.py
 | |
| # Purpose:      project model for wx.lib.pydocview
 | |
| #
 | |
| # Author:       Morgan Hua
 | |
| #
 | |
| # Created:      8/25/05
 | |
| # CVS-ID:       $Id$
 | |
| # Copyright:    (c) 2005 ActiveGrid, Inc.
 | |
| # License:      wxWindows License
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| import copy
 | |
| import os
 | |
| import os.path
 | |
| import activegrid.util.xmlutils as xmlutils
 | |
| from IDE import ACTIVEGRID_BASE_IDE
 | |
| if not ACTIVEGRID_BASE_IDE:
 | |
|     import activegrid.model.basedocmgr as basedocmgr
 | |
|     import AppInfo
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| # Constants
 | |
| #----------------------------------------------------------------------------
 | |
| # Always add new versions, never edit the version number
 | |
| # This allows you to upgrade the file by checking the version number
 | |
| PROJECT_VERSION_050730 = '10'
 | |
| PROJECT_VERSION_050826 = '11'
 | |
| 
 | |
|     
 | |
| #----------------------------------------------------------------------------
 | |
| # XML Marshalling Methods
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| def load(fileObject):
 | |
|     version = xmlutils.getAgVersion(fileObject.name)
 | |
|     # most current versions on top
 | |
|     if version == PROJECT_VERSION_050826:
 | |
|         fileObject.seek(0)
 | |
|         if ACTIVEGRID_BASE_IDE:
 | |
|             KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile}
 | |
|         else:
 | |
|             KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo}
 | |
|         project = xmlutils.load(fileObject.name, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES)
 | |
|     elif version == PROJECT_VERSION_050730:
 | |
|         fileObject.seek(0)
 | |
|         project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10})
 | |
|         project = project.upgradeVersion()
 | |
|     else:
 | |
|         # assume it is old version without version number
 | |
|         fileObject.seek(0)
 | |
|         project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10})
 | |
|         if project:
 | |
|             project = project.upgradeVersion()
 | |
|         else:
 | |
|             print "Project, unknown version:", version
 | |
|             return None
 | |
|             
 | |
|     if project:
 | |
|         project._projectDir = os.path.dirname(fileObject.name)
 | |
|         project.RelativeToAbsPath()
 | |
|         
 | |
|     return project
 | |
| 
 | |
| 
 | |
| def save(fileObject, project, productionDeployment=False):
 | |
|     if not project._projectDir:
 | |
|         project._projectDir = os.path.dirname(fileObject.name)
 | |
|     project.AbsToRelativePath()  # temporarily change it to relative paths for saving
 | |
|     if ACTIVEGRID_BASE_IDE:
 | |
|         KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile}
 | |
|     else:
 | |
|         KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo}
 | |
| 
 | |
|     savedHomeDir = project.homeDir        
 | |
|     if productionDeployment:
 | |
|         # for deployments, we don't want an abs path in homeDir since that
 | |
|         # would tie the app to the current filesystem. So unset it.
 | |
|         project.homeDir = None
 | |
|         
 | |
|     xmlutils.save(fileObject.name, project, prettyPrint=True, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES)
 | |
| 
 | |
|     if productionDeployment:
 | |
|         project.homeDir = savedHomeDir
 | |
|     
 | |
|     project.RelativeToAbsPath()  # swap it back to absolute path
 | |
| 
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| # Classes
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| class BaseProject(object):
 | |
| 
 | |
|     __xmlname__ = "project"
 | |
|     __xmlexclude__ = ('fileName', '_projectDir', '_getDocCallback')
 | |
|     __xmlattributes__ = ("_homeDir", "version")
 | |
|     __xmlrename__ = { "_homeDir":"homeDir", "_appInfo":"appInfo" }
 | |
|     __xmlflattensequence__ = { "_files":("file",) }
 | |
|     __xmldefaultnamespace__ = xmlutils.AG_NS_URL
 | |
|     __xmlattrnamespaces__ = { "ag": ["version", "_homeDir"] }
 | |
| 
 | |
| 
 | |
|     def __init__(self):
 | |
|         self.__xmlnamespaces__ = { "ag" : xmlutils.AG_NS_URL }
 | |
|         self.version = PROJECT_VERSION_050826
 | |
|         self._files = []
 | |
|         self._projectDir = None  # default for homeDir, set on load
 | |
|         self._homeDir = None         # user set homeDir for use in calculating relative path
 | |
|         if not ACTIVEGRID_BASE_IDE:
 | |
|             self._appInfo = AppInfo.AppInfo()
 | |
|         
 | |
| 
 | |
|     def __copy__(self):
 | |
|         clone = Project()
 | |
|         clone._files = [copy.copy(file) for file in self._files]
 | |
|         clone._projectDir = self._projectDir
 | |
|         clone._homeDir = self._homeDir
 | |
|         if not ACTIVEGRID_BASE_IDE:
 | |
|             clone._appInfo = self._appInfo
 | |
|         return clone
 | |
| 
 | |
|     
 | |
|     def initialize(self):
 | |
|         """ Required method for xmlmarshaller """
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def GetAppInfo(self):
 | |
|         return self._appInfo
 | |
|         
 | |
| 
 | |
|     def AddFile(self, filePath=None, logicalFolder=None, type=None, name=None, file=None):
 | |
|         """ Usage: self.AddFile(filePath, logicalFolder, type, name)  # used for initial generation of object
 | |
|                    self.AddFile(file=xyzFile)  # normally used for redo/undo
 | |
|             Add newly created file object using filePath and logicalFolder or given file object
 | |
|         """
 | |
|         if file:
 | |
|             self._files.append(file)
 | |
|         else:
 | |
|             self._files.append(ProjectFile(filePath, logicalFolder, type, name, getDocCallback=self._getDocCallback))
 | |
| 
 | |
| 
 | |
|     def RemoveFile(self, file):
 | |
|         self._files.remove(file)
 | |
| 
 | |
| 
 | |
|     def FindFile(self, filePath):
 | |
|         if filePath:
 | |
|             for file in self._files:
 | |
|                 if file.filePath == filePath:
 | |
|                     return file
 | |
|                 
 | |
|         return None
 | |
| 
 | |
| 
 | |
|     def _GetFilePaths(self):
 | |
|         return [file.filePath for file in self._files]
 | |
| 
 | |
| 
 | |
|     filePaths = property(_GetFilePaths)
 | |
| 
 | |
| 
 | |
|     def _GetLogicalFolders(self):
 | |
|         folders = []
 | |
|         for file in self._files:
 | |
|             if file.logicalFolder and file.logicalFolder not in folders:
 | |
|                 folders.append(file.logicalFolder)
 | |
|         return folders
 | |
| 
 | |
| 
 | |
|     logicalFolders = property(_GetLogicalFolders)
 | |
|     
 | |
| 
 | |
|     def _GetPhysicalFolders(self):
 | |
|         physicalFolders = []
 | |
|         for file in self._files:
 | |
|             physicalFolder = file.physicalFolder
 | |
|             if physicalFolder and physicalFolder not in physicalFolders:
 | |
|                 physicalFolders.append(physicalFolder)
 | |
|         return physicalFolders
 | |
| 
 | |
| 
 | |
|     physicalFolders = property(_GetPhysicalFolders)
 | |
| 
 | |
| 
 | |
|     def _GetHomeDir(self):
 | |
|         if self._homeDir:
 | |
|             return self._homeDir
 | |
|         else:
 | |
|             return self._projectDir
 | |
|         
 | |
| 
 | |
|     def _SetHomeDir(self, parentPath):
 | |
|         self._homeDir = parentPath
 | |
|         
 | |
| 
 | |
|     def _IsDefaultHomeDir(self):
 | |
|         return (self._homeDir == None)
 | |
| 
 | |
| 
 | |
|     isDefaultHomeDir = property(_IsDefaultHomeDir)
 | |
| 
 | |
| 
 | |
|     homeDir = property(_GetHomeDir, _SetHomeDir)
 | |
| 
 | |
| 
 | |
|     def GetRelativeFolders(self):
 | |
|         relativeFolders = []
 | |
|         for file in self._files:
 | |
|             relFolder = file.GetRelativeFolder(self.homeDir)
 | |
|             if relFolder and relFolder not in relativeFolders:
 | |
|                 relativeFolders.append(relFolder)
 | |
|         return relativeFolders
 | |
|         
 | |
| 
 | |
|     def AbsToRelativePath(self):
 | |
|         for file in self._files:
 | |
|             file.AbsToRelativePath(self.homeDir)
 | |
| 
 | |
| 
 | |
|     def RelativeToAbsPath(self):
 | |
|         for file in self._files:
 | |
|             file.RelativeToAbsPath(self.homeDir)
 | |
| 
 | |
| 
 | |
|     #----------------------------------------------------------------------------
 | |
|     # BaseDocumentMgr methods
 | |
|     #----------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
|     def fullPath(self, fileName):
 | |
|         fileName = super(BaseProject, self).fullPath(fileName)
 | |
|         
 | |
|         if os.path.isabs(fileName):
 | |
|             absPath = fileName
 | |
|         elif self.homeDir:
 | |
|             absPath = os.path.join(self.homeDir, fileName)
 | |
|         else:
 | |
|             absPath = os.path.abspath(fileName)
 | |
|         return os.path.normpath(absPath)
 | |
| 
 | |
| 
 | |
|     def documentRefFactory(self, name, fileType, filePath):
 | |
|         return ProjectFile(filePath=self.fullPath(filePath), type=fileType, name=name, getDocCallback=self._getDocCallback)
 | |
| 
 | |
| 
 | |
|     def findAllRefs(self):
 | |
|         return self._files
 | |
| 
 | |
| 
 | |
|     def GetXFormsDirectory(self):
 | |
|         forms = self.findRefsByFileType(basedocmgr.FILE_TYPE_XFORM)
 | |
|         filePaths = map(lambda form: form.filePath, forms)
 | |
|         xformdir = os.path.commonprefix(filePaths)
 | |
|         if not xformdir:
 | |
|             xformdir = self.homeDir
 | |
|         return xformdir
 | |
|          
 | |
|    
 | |
|     def setRefs(self, files):
 | |
|         self._files = files
 | |
| 
 | |
| 
 | |
|     def findRefsByFileType(self, fileType):
 | |
|         fileList = []
 | |
|         for file in self._files:
 | |
|             if fileType == file.type:
 | |
|                 fileList.append(file)
 | |
|         return fileList
 | |
| 
 | |
| 
 | |
|     def GenerateServiceRefPath(self, wsdlFilePath):
 | |
|         # HACK: temporary solution to getting wsdlag path from wsdl path.
 | |
|         import wx
 | |
|         from WsdlAgEditor import WsdlAgDocument
 | |
|         ext = WsdlAgDocument.WSDL_AG_EXT
 | |
|         for template in wx.GetApp().GetDocumentManager().GetTemplates():
 | |
|             if template.GetDocumentType() == WsdlAgDocument:
 | |
|                 ext = template.GetDefaultExtension()
 | |
|                 break;
 | |
|         wsdlAgFilePath = os.path.splitext(wsdlFilePath)[0] + ext
 | |
|         return wsdlAgFilePath
 | |
| 
 | |
| 
 | |
|     def SetDocCallback(self, getDocCallback):
 | |
|         self._getDocCallback = getDocCallback
 | |
|         for file in self._files:
 | |
|             file._getDocCallback = getDocCallback
 | |
| 
 | |
| 
 | |
| if ACTIVEGRID_BASE_IDE:
 | |
|     class Project(BaseProject):
 | |
|         pass
 | |
| else:
 | |
|     class Project(BaseProject, basedocmgr.BaseDocumentMgr):
 | |
|         pass
 | |
|         
 | |
| 
 | |
| class ProjectFile(object):
 | |
|     __xmlname__ = "file"
 | |
|     __xmlexclude__ = ('_getDocCallback', '_docCallbackCacheReturnValue', '_docModelCallbackCacheReturnValue', '_doc',)
 | |
|     __xmlattributes__ = ["filePath", "logicalFolder", "type", "name"]
 | |
|     __xmldefaultnamespace__ = xmlutils.AG_NS_URL
 | |
| 
 | |
| 
 | |
|     def __init__(self, filePath=None, logicalFolder=None, type=None, name=None, getDocCallback=None):
 | |
|         self.filePath = filePath
 | |
|         self.logicalFolder = logicalFolder
 | |
|         self.type = type
 | |
|         self.name = name
 | |
|         self._getDocCallback = getDocCallback
 | |
|         self._docCallbackCacheReturnValue = None
 | |
|         self._docModelCallbackCacheReturnValue = None
 | |
|         self._doc = None
 | |
| 
 | |
| 
 | |
|     def _GetDocumentModel(self):
 | |
|         # possible bug is if document gets replaced outside of IDE, where we'll return previous doc.
 | |
|         # originally added a timestamp check but that increased the time again to 4x
 | |
|         if self._docModelCallbackCacheReturnValue:  # accelerator for caching document, got 4x speed up.
 | |
|             return self._docModelCallbackCacheReturnValue
 | |
|             
 | |
|         if self._getDocCallback:
 | |
|             self._docCallbackCacheReturnValue, self._docModelCallbackCacheReturnValue = self._getDocCallback(self.filePath)
 | |
|             return self._docModelCallbackCacheReturnValue
 | |
|             
 | |
|         return None
 | |
| 
 | |
|         
 | |
|     document = property(_GetDocumentModel)
 | |
|     
 | |
| 
 | |
|     def _GetDocument(self):
 | |
|         # Hack, just return the IDE document wrapper that corresponds to the runtime document model
 | |
|         # callers should have called ".document" before calling ".ideDocument"
 | |
|         if self._docCallbackCacheReturnValue:  # accelerator for caching document, got 4x speed up.
 | |
|             return self._docCallbackCacheReturnValue
 | |
|         return None
 | |
|     
 | |
| 
 | |
|     ideDocument = property(_GetDocument)
 | |
| 
 | |
| 
 | |
|     def _typeEnumeration(self):
 | |
|         return basedocmgr.FILE_TYPE_LIST
 | |
|         
 | |
| 
 | |
|     def _GetPhysicalFolder(self):
 | |
|         dir = None
 | |
|         if self.filePath:
 | |
|             dir = os.path.dirname(self.filePath)
 | |
|             if os.sep != '/':
 | |
|                 dir = dir.replace(os.sep, '/')  # require '/' as delimiter
 | |
|         return dir
 | |
| 
 | |
| 
 | |
|     physicalFolder = property(_GetPhysicalFolder)
 | |
|     
 | |
| 
 | |
|     def GetRelativeFolder(self, parentPath):
 | |
|         parentPathLen = len(parentPath)
 | |
| 
 | |
|         dir = None
 | |
|         if self.filePath:
 | |
|             dir = os.path.dirname(self.filePath)
 | |
|             if dir.startswith(parentPath):
 | |
|                 dir = "." + dir[parentPathLen:]  # convert to relative path
 | |
|             if os.sep != '/':
 | |
|                 dir = dir.replace(os.sep, '/')  # always save out with '/' as path separator for cross-platform compatibility.
 | |
|         return dir
 | |
| 
 | |
| 
 | |
|     def AbsToRelativePath(self, parentPath):
 | |
|         """ Used to convert path to relative path for saving (disk format) """
 | |
|         parentPathLen = len(parentPath)
 | |
| 
 | |
|         if self.filePath.startswith(parentPath):
 | |
|             self.filePath = "." + self.filePath[parentPathLen:]  # convert to relative path
 | |
|             if os.sep != '/':
 | |
|                 self.filePath = self.filePath.replace(os.sep, '/')  # always save out with '/' as path separator for cross-platform compatibility.
 | |
|         else:
 | |
|             pass    # not a decendant of project, use absolute path
 | |
| 
 | |
| 
 | |
|     def RelativeToAbsPath(self, parentPath):
 | |
|         """ Used to convert path to absolute path (for any necessary disk access) """
 | |
|         if self.filePath.startswith("."):  # relative to project file
 | |
|             self.filePath = os.path.normpath(os.path.join(parentPath, self.filePath))
 | |
| 
 | |
| 
 | |
|     #----------------------------------------------------------------------------
 | |
|     # BaseDocumentMgr methods
 | |
|     #----------------------------------------------------------------------------
 | |
| 
 | |
|     def _GetDoc(self):
 | |
|         # HACK: temporary solution.
 | |
|         import wx
 | |
|         import wx.lib.docview
 | |
|         if not self._doc:
 | |
|             docMgr = wx.GetApp().GetDocumentManager()
 | |
|             
 | |
|             doc = docMgr.CreateDocument(self.filePath, docMgr.GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW)
 | |
|             if (doc == None):  # already open
 | |
|                 docs = docMgr.GetDocuments()
 | |
|                 for d in docs:
 | |
|                     if d.GetFilename() == self.filePath:
 | |
|                         doc = d
 | |
|                         break
 | |
|             self._doc = doc
 | |
|         return self._doc
 | |
|         
 | |
| 
 | |
|     def _GetLocalServiceProcessName(self):
 | |
|         # HACK: temporary solution to getting process name from wsdlag file.
 | |
|         return self._GetDoc().GetModel().processName
 | |
| 
 | |
| 
 | |
|     processName = property(_GetLocalServiceProcessName)
 | |
| 
 | |
| 
 | |
|     def _GetStateful(self):
 | |
|         # HACK: temporary solution to getting stateful from wsdlag file.
 | |
|         return self._GetDoc().GetModel().stateful
 | |
| 
 | |
| 
 | |
|     def _SetStateful(self, stateful):
 | |
|         # HACK: temporary solution to setting stateful from wsdlag file.
 | |
|         self._GetDoc().GetModel().stateful = stateful
 | |
| 
 | |
| 
 | |
|     stateful = property(_GetStateful, _SetStateful)
 | |
| 
 | |
| 
 | |
|     def _GetLocalServiceCodeFile(self):
 | |
|         # HACK: temporary solution to getting class name from wsdlag file.
 | |
|         return self._GetDoc().GetModel().localServiceCodeFile
 | |
| 
 | |
| 
 | |
|     def _SetLocalServiceCodeFile(self, codefile):
 | |
|         # HACK: temporary solution to setting class name from wsdlag file.
 | |
|         self._GetDoc().GetModel().localServiceCodeFile = codefile
 | |
| 
 | |
| 
 | |
|     localServiceCodeFile = property(_GetLocalServiceCodeFile, _SetLocalServiceCodeFile)
 | |
| 
 | |
| 
 | |
|     def _GetLocalServiceClassName(self):
 | |
|         # HACK: temporary solution to getting class name from wsdlag file.
 | |
|         return self._GetDoc().GetModel().localServiceClassName
 | |
| 
 | |
| 
 | |
|     def _SetLocalServiceClassName(self, className):
 | |
|         # HACK: temporary solution to setting class name from wsdlag file.
 | |
|         self._GetDoc().GetModel().localServiceClassName = className
 | |
| 
 | |
| 
 | |
|     localServiceClassName = property(_GetLocalServiceClassName, _SetLocalServiceClassName)
 | |
| 
 | |
| 
 | |
| 
 | |
| # only activate this code if we programatically need to access these values
 | |
| ##    def _GetRssServiceBaseURL(self):
 | |
| ##        return self._GetDoc().GetModel().rssServiceBaseURL
 | |
| ##
 | |
| ##        
 | |
| ##    def _SetRssServiceBaseURL(self, baseURL):
 | |
| ##        self._GetDoc().GetModel().rssServiceBaseURL = baseURL
 | |
| ##         
 | |
| ##   
 | |
| ##    rssServiceBaseURL = property(_GetRssServiceBaseURL, _SetRssServiceBaseURL)
 | |
| ##
 | |
| ##
 | |
| ##    def _GetRssServiceRssVersion(self):
 | |
| ##        return self._GetDoc().GetModel().rssServiceRssVersion
 | |
| ##        
 | |
| ##
 | |
| ##    def _SetRssServiceRssVersion(self, rssVersion):
 | |
| ##        self._GetDoc().GetModel().rssServiceRssVersion = rssVersion
 | |
| ##            
 | |
| ##
 | |
| ##    rssServiceRssVersion = property(_GetRssServiceRssVersion, _SetRssServiceRssVersion)
 | |
| 
 | |
| 
 | |
|     def _GetServiceRefServiceType(self):
 | |
|         # HACK: temporary solution to getting service type from wsdlag file.
 | |
|         model = self._GetDoc().GetModel()
 | |
|         if hasattr(model, 'serviceType'):
 | |
|             return model.serviceType
 | |
|         else:
 | |
|             return None
 | |
| 
 | |
| 
 | |
|     def _SetServiceRefServiceType(self, serviceType):
 | |
|         # HACK: temporary solution to getting service type from wsdlag file.
 | |
|         self._GetDoc().GetModel().serviceType = serviceType
 | |
|         
 | |
| 
 | |
|     serviceType = property(_GetServiceRefServiceType, _SetServiceRefServiceType)
 | |
| 
 | |
| 
 | |
|     def getExternalPackage(self):
 | |
|         # HACK: temporary solution to getting custom code filename from wsdlag file.
 | |
|         import activegrid.server.deployment as deploymentlib    
 | |
|         
 | |
|         appInfo = self._GetDoc().GetAppInfo()
 | |
| 
 | |
|         if appInfo.language == None:
 | |
|             language = deploymentlib.LANGUAGE_DEFAULT
 | |
|         else:
 | |
|             language = appInfo.language
 | |
|             
 | |
|         if language == deploymentlib.LANGUAGE_PYTHON:
 | |
|             suffix = ".py"
 | |
|         elif language == deploymentlib.LANGUAGE_PHP:
 | |
|             suffix = ".php"
 | |
|         pyFilename = self.name + suffix
 | |
|         return self._GetDoc().GetAppDocMgr().fullPath(pyFilename)
 | |
| 
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| # Old Classes
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| class Project_10:
 | |
|     """ Version 1.0, kept for upgrading to latest version.  Over time, this should be deprecated. """
 | |
|     __xmlname__ = "project"
 | |
|     __xmlrename__ = { "_files":"files"}
 | |
|     __xmlexclude__ = ('fileName',)
 | |
|     __xmlattributes__ = ["version"]
 | |
| 
 | |
| 
 | |
|     def __init__(self):
 | |
|         self.version = PROJECT_VERSION_050730
 | |
|         self._files = []
 | |
| 
 | |
| 
 | |
|     def initialize(self):
 | |
|         """ Required method for xmlmarshaller """
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def upgradeVersion(self):
 | |
|         currModel = Project()
 | |
|         for file in self._files:
 | |
|             currModel._files.append(ProjectFile(file))
 | |
|         return currModel
 | |
| 
 | |
| 
 |