]>
Commit | Line | Data |
---|---|---|
02b800ce RD |
1 | #---------------------------------------------------------------------------- |
2 | # Name: project.py | |
3 | # Purpose: project model for wx.lib.pydocview | |
4 | # | |
5 | # Author: Morgan Hua | |
6 | # | |
7 | # Created: 8/25/05 | |
8 | # CVS-ID: $Id$ | |
9 | # Copyright: (c) 2005 ActiveGrid, Inc. | |
10 | # License: wxWindows License | |
11 | #---------------------------------------------------------------------------- | |
12 | ||
13 | import copy | |
14 | import os | |
15 | import os.path | |
16 | import activegrid.util.xmlutils as xmlutils | |
17 | from IDE import ACTIVEGRID_BASE_IDE | |
18 | if not ACTIVEGRID_BASE_IDE: | |
19 | import activegrid.model.basedocmgr as basedocmgr | |
20 | import AppInfo | |
21 | ||
22 | #---------------------------------------------------------------------------- | |
23 | # Constants | |
24 | #---------------------------------------------------------------------------- | |
25 | # Always add new versions, never edit the version number | |
26 | # This allows you to upgrade the file by checking the version number | |
27 | PROJECT_VERSION_050730 = '10' | |
28 | PROJECT_VERSION_050826 = '11' | |
29 | ||
30 | ||
31 | #---------------------------------------------------------------------------- | |
32 | # XML Marshalling Methods | |
33 | #---------------------------------------------------------------------------- | |
34 | ||
35 | def load(fileObject): | |
36 | version = xmlutils.getAgVersion(fileObject.name) | |
37 | # most current versions on top | |
38 | if version == PROJECT_VERSION_050826: | |
39 | fileObject.seek(0) | |
40 | if ACTIVEGRID_BASE_IDE: | |
41 | KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile} | |
42 | else: | |
43 | KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo} | |
44 | project = xmlutils.load(fileObject.name, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES) | |
45 | elif version == PROJECT_VERSION_050730: | |
46 | fileObject.seek(0) | |
47 | project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}) | |
48 | project = project.upgradeVersion() | |
49 | else: | |
50 | # assume it is old version without version number | |
51 | fileObject.seek(0) | |
52 | project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}) | |
53 | if project: | |
54 | project = project.upgradeVersion() | |
55 | else: | |
56 | print "Project, unknown version:", version | |
57 | return None | |
58 | ||
59 | if project: | |
60 | project._projectDir = os.path.dirname(fileObject.name) | |
61 | project.RelativeToAbsPath() | |
62 | ||
63 | return project | |
64 | ||
65 | ||
66 | def save(fileObject, project, productionDeployment=False): | |
67 | if not project._projectDir: | |
68 | project._projectDir = os.path.dirname(fileObject.name) | |
69 | project.AbsToRelativePath() # temporarily change it to relative paths for saving | |
70 | if ACTIVEGRID_BASE_IDE: | |
71 | KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile} | |
72 | else: | |
73 | KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo} | |
74 | ||
75 | savedHomeDir = project.homeDir | |
76 | if productionDeployment: | |
77 | # for deployments, we don't want an abs path in homeDir since that | |
78 | # would tie the app to the current filesystem. So unset it. | |
79 | project.homeDir = None | |
80 | ||
81 | xmlutils.save(fileObject.name, project, prettyPrint=True, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES) | |
82 | ||
83 | if productionDeployment: | |
84 | project.homeDir = savedHomeDir | |
85 | ||
86 | project.RelativeToAbsPath() # swap it back to absolute path | |
87 | ||
88 | ||
89 | #---------------------------------------------------------------------------- | |
90 | # Classes | |
91 | #---------------------------------------------------------------------------- | |
92 | ||
93 | class BaseProject(object): | |
94 | ||
95 | __xmlname__ = "project" | |
96 | __xmlexclude__ = ('fileName', '_projectDir', '_getDocCallback') | |
97 | __xmlattributes__ = ("_homeDir", "version") | |
98 | __xmlrename__ = { "_homeDir":"homeDir", "_appInfo":"appInfo" } | |
99 | __xmlflattensequence__ = { "_files":("file",) } | |
100 | __xmldefaultnamespace__ = xmlutils.AG_NS_URL | |
101 | __xmlattrnamespaces__ = { "ag": ["version", "_homeDir"] } | |
102 | ||
103 | ||
104 | def __init__(self): | |
105 | self.__xmlnamespaces__ = { "ag" : xmlutils.AG_NS_URL } | |
106 | self.version = PROJECT_VERSION_050826 | |
107 | self._files = [] | |
108 | self._projectDir = None # default for homeDir, set on load | |
109 | self._homeDir = None # user set homeDir for use in calculating relative path | |
110 | if not ACTIVEGRID_BASE_IDE: | |
111 | self._appInfo = AppInfo.AppInfo() | |
112 | ||
113 | ||
114 | def __copy__(self): | |
115 | clone = Project() | |
116 | clone._files = [copy.copy(file) for file in self._files] | |
117 | clone._projectDir = self._projectDir | |
118 | clone._homeDir = self._homeDir | |
119 | if not ACTIVEGRID_BASE_IDE: | |
120 | clone._appInfo = self._appInfo | |
121 | return clone | |
122 | ||
123 | ||
124 | def initialize(self): | |
125 | """ Required method for xmlmarshaller """ | |
126 | pass | |
127 | ||
128 | ||
129 | def GetAppInfo(self): | |
130 | return self._appInfo | |
131 | ||
132 | ||
133 | def AddFile(self, filePath=None, logicalFolder=None, type=None, name=None, file=None): | |
134 | """ Usage: self.AddFile(filePath, logicalFolder, type, name) # used for initial generation of object | |
135 | self.AddFile(file=xyzFile) # normally used for redo/undo | |
136 | Add newly created file object using filePath and logicalFolder or given file object | |
137 | """ | |
138 | if file: | |
139 | self._files.append(file) | |
140 | else: | |
141 | self._files.append(ProjectFile(filePath, logicalFolder, type, name, getDocCallback=self._getDocCallback)) | |
142 | ||
143 | ||
144 | def RemoveFile(self, file): | |
145 | self._files.remove(file) | |
146 | ||
147 | ||
148 | def FindFile(self, filePath): | |
149 | if filePath: | |
150 | for file in self._files: | |
151 | if file.filePath == filePath: | |
152 | return file | |
153 | ||
154 | return None | |
155 | ||
156 | ||
157 | def _GetFilePaths(self): | |
158 | return [file.filePath for file in self._files] | |
159 | ||
160 | ||
161 | filePaths = property(_GetFilePaths) | |
162 | ||
163 | ||
164 | def _GetLogicalFolders(self): | |
165 | folders = [] | |
166 | for file in self._files: | |
167 | if file.logicalFolder and file.logicalFolder not in folders: | |
168 | folders.append(file.logicalFolder) | |
169 | return folders | |
170 | ||
171 | ||
172 | logicalFolders = property(_GetLogicalFolders) | |
173 | ||
174 | ||
175 | def _GetPhysicalFolders(self): | |
176 | physicalFolders = [] | |
177 | for file in self._files: | |
178 | physicalFolder = file.physicalFolder | |
179 | if physicalFolder and physicalFolder not in physicalFolders: | |
180 | physicalFolders.append(physicalFolder) | |
181 | return physicalFolders | |
182 | ||
183 | ||
184 | physicalFolders = property(_GetPhysicalFolders) | |
185 | ||
186 | ||
187 | def _GetHomeDir(self): | |
188 | if self._homeDir: | |
189 | return self._homeDir | |
190 | else: | |
191 | return self._projectDir | |
192 | ||
193 | ||
194 | def _SetHomeDir(self, parentPath): | |
195 | self._homeDir = parentPath | |
196 | ||
197 | ||
198 | def _IsDefaultHomeDir(self): | |
199 | return (self._homeDir == None) | |
200 | ||
201 | ||
202 | isDefaultHomeDir = property(_IsDefaultHomeDir) | |
203 | ||
204 | ||
205 | homeDir = property(_GetHomeDir, _SetHomeDir) | |
206 | ||
207 | ||
208 | def GetRelativeFolders(self): | |
209 | relativeFolders = [] | |
210 | for file in self._files: | |
211 | relFolder = file.GetRelativeFolder(self.homeDir) | |
212 | if relFolder and relFolder not in relativeFolders: | |
213 | relativeFolders.append(relFolder) | |
214 | return relativeFolders | |
215 | ||
216 | ||
217 | def AbsToRelativePath(self): | |
218 | for file in self._files: | |
219 | file.AbsToRelativePath(self.homeDir) | |
220 | ||
221 | ||
222 | def RelativeToAbsPath(self): | |
223 | for file in self._files: | |
224 | file.RelativeToAbsPath(self.homeDir) | |
225 | ||
226 | ||
227 | #---------------------------------------------------------------------------- | |
228 | # BaseDocumentMgr methods | |
229 | #---------------------------------------------------------------------------- | |
230 | ||
231 | ||
232 | def fullPath(self, fileName): | |
233 | fileName = super(BaseProject, self).fullPath(fileName) | |
234 | ||
235 | if os.path.isabs(fileName): | |
236 | absPath = fileName | |
237 | elif self.homeDir: | |
238 | absPath = os.path.join(self.homeDir, fileName) | |
239 | else: | |
240 | absPath = os.path.abspath(fileName) | |
241 | return os.path.normpath(absPath) | |
242 | ||
243 | ||
244 | def documentRefFactory(self, name, fileType, filePath): | |
245 | return ProjectFile(filePath=self.fullPath(filePath), type=fileType, name=name, getDocCallback=self._getDocCallback) | |
246 | ||
247 | ||
248 | def findAllRefs(self): | |
249 | return self._files | |
250 | ||
251 | ||
252 | def GetXFormsDirectory(self): | |
253 | forms = self.findRefsByFileType(basedocmgr.FILE_TYPE_XFORM) | |
254 | filePaths = map(lambda form: form.filePath, forms) | |
255 | xformdir = os.path.commonprefix(filePaths) | |
256 | if not xformdir: | |
257 | xformdir = self.homeDir | |
258 | return xformdir | |
259 | ||
260 | ||
261 | def setRefs(self, files): | |
262 | self._files = files | |
263 | ||
264 | ||
265 | def findRefsByFileType(self, fileType): | |
266 | fileList = [] | |
267 | for file in self._files: | |
268 | if fileType == file.type: | |
269 | fileList.append(file) | |
270 | return fileList | |
271 | ||
272 | ||
273 | def GenerateServiceRefPath(self, wsdlFilePath): | |
274 | # HACK: temporary solution to getting wsdlag path from wsdl path. | |
275 | import wx | |
276 | from WsdlAgEditor import WsdlAgDocument | |
277 | ext = WsdlAgDocument.WSDL_AG_EXT | |
278 | for template in wx.GetApp().GetDocumentManager().GetTemplates(): | |
279 | if template.GetDocumentType() == WsdlAgDocument: | |
280 | ext = template.GetDefaultExtension() | |
281 | break; | |
282 | wsdlAgFilePath = os.path.splitext(wsdlFilePath)[0] + ext | |
283 | return wsdlAgFilePath | |
284 | ||
285 | ||
286 | def SetDocCallback(self, getDocCallback): | |
287 | self._getDocCallback = getDocCallback | |
288 | for file in self._files: | |
289 | file._getDocCallback = getDocCallback | |
290 | ||
291 | ||
292 | if ACTIVEGRID_BASE_IDE: | |
293 | class Project(BaseProject): | |
294 | pass | |
295 | else: | |
296 | class Project(BaseProject, basedocmgr.BaseDocumentMgr): | |
297 | pass | |
298 | ||
299 | ||
300 | class ProjectFile(object): | |
301 | __xmlname__ = "file" | |
302 | __xmlexclude__ = ('_getDocCallback', '_docCallbackCacheReturnValue', '_docModelCallbackCacheReturnValue', '_doc',) | |
303 | __xmlattributes__ = ["filePath", "logicalFolder", "type", "name"] | |
304 | __xmldefaultnamespace__ = xmlutils.AG_NS_URL | |
305 | ||
306 | ||
307 | def __init__(self, filePath=None, logicalFolder=None, type=None, name=None, getDocCallback=None): | |
308 | self.filePath = filePath | |
309 | self.logicalFolder = logicalFolder | |
310 | self.type = type | |
311 | self.name = name | |
312 | self._getDocCallback = getDocCallback | |
313 | self._docCallbackCacheReturnValue = None | |
314 | self._docModelCallbackCacheReturnValue = None | |
315 | self._doc = None | |
316 | ||
317 | ||
318 | def _GetDocumentModel(self): | |
319 | # possible bug is if document gets replaced outside of IDE, where we'll return previous doc. | |
320 | # originally added a timestamp check but that increased the time again to 4x | |
321 | if self._docModelCallbackCacheReturnValue: # accelerator for caching document, got 4x speed up. | |
322 | return self._docModelCallbackCacheReturnValue | |
323 | ||
324 | if self._getDocCallback: | |
325 | self._docCallbackCacheReturnValue, self._docModelCallbackCacheReturnValue = self._getDocCallback(self.filePath) | |
326 | return self._docModelCallbackCacheReturnValue | |
327 | ||
328 | return None | |
329 | ||
330 | ||
331 | document = property(_GetDocumentModel) | |
332 | ||
333 | ||
334 | def _GetDocument(self): | |
335 | # Hack, just return the IDE document wrapper that corresponds to the runtime document model | |
336 | # callers should have called ".document" before calling ".ideDocument" | |
337 | if self._docCallbackCacheReturnValue: # accelerator for caching document, got 4x speed up. | |
338 | return self._docCallbackCacheReturnValue | |
339 | return None | |
340 | ||
341 | ||
342 | ideDocument = property(_GetDocument) | |
343 | ||
344 | ||
345 | def _typeEnumeration(self): | |
346 | return basedocmgr.FILE_TYPE_LIST | |
347 | ||
348 | ||
349 | def _GetPhysicalFolder(self): | |
350 | dir = None | |
351 | if self.filePath: | |
352 | dir = os.path.dirname(self.filePath) | |
353 | if os.sep != '/': | |
354 | dir = dir.replace(os.sep, '/') # require '/' as delimiter | |
355 | return dir | |
356 | ||
357 | ||
358 | physicalFolder = property(_GetPhysicalFolder) | |
359 | ||
360 | ||
361 | def GetRelativeFolder(self, parentPath): | |
362 | parentPathLen = len(parentPath) | |
363 | ||
364 | dir = None | |
365 | if self.filePath: | |
366 | dir = os.path.dirname(self.filePath) | |
367 | if dir.startswith(parentPath): | |
368 | dir = "." + dir[parentPathLen:] # convert to relative path | |
369 | if os.sep != '/': | |
370 | dir = dir.replace(os.sep, '/') # always save out with '/' as path separator for cross-platform compatibility. | |
371 | return dir | |
372 | ||
373 | ||
374 | def AbsToRelativePath(self, parentPath): | |
375 | """ Used to convert path to relative path for saving (disk format) """ | |
376 | parentPathLen = len(parentPath) | |
377 | ||
378 | if self.filePath.startswith(parentPath): | |
379 | self.filePath = "." + self.filePath[parentPathLen:] # convert to relative path | |
380 | if os.sep != '/': | |
381 | self.filePath = self.filePath.replace(os.sep, '/') # always save out with '/' as path separator for cross-platform compatibility. | |
382 | else: | |
383 | pass # not a decendant of project, use absolute path | |
384 | ||
385 | ||
386 | def RelativeToAbsPath(self, parentPath): | |
387 | """ Used to convert path to absolute path (for any necessary disk access) """ | |
388 | if self.filePath.startswith("."): # relative to project file | |
389 | self.filePath = os.path.normpath(os.path.join(parentPath, self.filePath)) | |
390 | ||
391 | ||
392 | #---------------------------------------------------------------------------- | |
393 | # BaseDocumentMgr methods | |
394 | #---------------------------------------------------------------------------- | |
395 | ||
396 | def _GetDoc(self): | |
397 | # HACK: temporary solution. | |
398 | import wx | |
399 | import wx.lib.docview | |
400 | if not self._doc: | |
401 | docMgr = wx.GetApp().GetDocumentManager() | |
402 | ||
403 | doc = docMgr.CreateDocument(self.filePath, docMgr.GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW) | |
404 | if (doc == None): # already open | |
405 | docs = docMgr.GetDocuments() | |
406 | for d in docs: | |
407 | if d.GetFilename() == self.filePath: | |
408 | doc = d | |
409 | break | |
410 | self._doc = doc | |
411 | return self._doc | |
412 | ||
413 | ||
414 | def _GetLocalServiceProcessName(self): | |
415 | # HACK: temporary solution to getting process name from wsdlag file. | |
416 | return self._GetDoc().GetModel().processName | |
417 | ||
418 | ||
419 | processName = property(_GetLocalServiceProcessName) | |
420 | ||
421 | ||
422 | def _GetStateful(self): | |
423 | # HACK: temporary solution to getting stateful from wsdlag file. | |
424 | return self._GetDoc().GetModel().stateful | |
425 | ||
426 | ||
427 | def _SetStateful(self, stateful): | |
428 | # HACK: temporary solution to setting stateful from wsdlag file. | |
429 | self._GetDoc().GetModel().stateful = stateful | |
430 | ||
431 | ||
432 | stateful = property(_GetStateful, _SetStateful) | |
433 | ||
434 | ||
435 | def _GetLocalServiceCodeFile(self): | |
436 | # HACK: temporary solution to getting class name from wsdlag file. | |
437 | return self._GetDoc().GetModel().localServiceCodeFile | |
438 | ||
439 | ||
440 | def _SetLocalServiceCodeFile(self, codefile): | |
441 | # HACK: temporary solution to setting class name from wsdlag file. | |
442 | self._GetDoc().GetModel().localServiceCodeFile = codefile | |
443 | ||
444 | ||
445 | localServiceCodeFile = property(_GetLocalServiceCodeFile, _SetLocalServiceCodeFile) | |
446 | ||
447 | ||
448 | def _GetLocalServiceClassName(self): | |
449 | # HACK: temporary solution to getting class name from wsdlag file. | |
450 | return self._GetDoc().GetModel().localServiceClassName | |
451 | ||
452 | ||
453 | def _SetLocalServiceClassName(self, className): | |
454 | # HACK: temporary solution to setting class name from wsdlag file. | |
455 | self._GetDoc().GetModel().localServiceClassName = className | |
456 | ||
457 | ||
458 | localServiceClassName = property(_GetLocalServiceClassName, _SetLocalServiceClassName) | |
459 | ||
460 | ||
461 | ||
462 | # only activate this code if we programatically need to access these values | |
463 | ## def _GetRssServiceBaseURL(self): | |
464 | ## return self._GetDoc().GetModel().rssServiceBaseURL | |
465 | ## | |
466 | ## | |
467 | ## def _SetRssServiceBaseURL(self, baseURL): | |
468 | ## self._GetDoc().GetModel().rssServiceBaseURL = baseURL | |
469 | ## | |
470 | ## | |
471 | ## rssServiceBaseURL = property(_GetRssServiceBaseURL, _SetRssServiceBaseURL) | |
472 | ## | |
473 | ## | |
474 | ## def _GetRssServiceRssVersion(self): | |
475 | ## return self._GetDoc().GetModel().rssServiceRssVersion | |
476 | ## | |
477 | ## | |
478 | ## def _SetRssServiceRssVersion(self, rssVersion): | |
479 | ## self._GetDoc().GetModel().rssServiceRssVersion = rssVersion | |
480 | ## | |
481 | ## | |
482 | ## rssServiceRssVersion = property(_GetRssServiceRssVersion, _SetRssServiceRssVersion) | |
483 | ||
484 | ||
485 | def _GetServiceRefServiceType(self): | |
486 | # HACK: temporary solution to getting service type from wsdlag file. | |
487 | model = self._GetDoc().GetModel() | |
488 | if hasattr(model, 'serviceType'): | |
489 | return model.serviceType | |
490 | else: | |
491 | return None | |
492 | ||
493 | ||
494 | def _SetServiceRefServiceType(self, serviceType): | |
495 | # HACK: temporary solution to getting service type from wsdlag file. | |
496 | self._GetDoc().GetModel().serviceType = serviceType | |
497 | ||
498 | ||
499 | serviceType = property(_GetServiceRefServiceType, _SetServiceRefServiceType) | |
500 | ||
501 | ||
502 | def getExternalPackage(self): | |
503 | # HACK: temporary solution to getting custom code filename from wsdlag file. | |
504 | import activegrid.server.deployment as deploymentlib | |
505 | ||
506 | appInfo = self._GetDoc().GetAppInfo() | |
507 | ||
508 | if appInfo.language == None: | |
509 | language = deploymentlib.LANGUAGE_DEFAULT | |
510 | else: | |
511 | language = appInfo.language | |
512 | ||
513 | if language == deploymentlib.LANGUAGE_PYTHON: | |
514 | suffix = ".py" | |
515 | elif language == deploymentlib.LANGUAGE_PHP: | |
516 | suffix = ".php" | |
517 | pyFilename = self.name + suffix | |
518 | return self._GetDoc().GetAppDocMgr().fullPath(pyFilename) | |
519 | ||
520 | ||
521 | #---------------------------------------------------------------------------- | |
522 | # Old Classes | |
523 | #---------------------------------------------------------------------------- | |
524 | ||
525 | class Project_10: | |
526 | """ Version 1.0, kept for upgrading to latest version. Over time, this should be deprecated. """ | |
527 | __xmlname__ = "project" | |
528 | __xmlrename__ = { "_files":"files"} | |
529 | __xmlexclude__ = ('fileName',) | |
530 | __xmlattributes__ = ["version"] | |
531 | ||
532 | ||
533 | def __init__(self): | |
534 | self.version = PROJECT_VERSION_050730 | |
535 | self._files = [] | |
536 | ||
537 | ||
538 | def initialize(self): | |
539 | """ Required method for xmlmarshaller """ | |
540 | pass | |
541 | ||
542 | ||
543 | def upgradeVersion(self): | |
544 | currModel = Project() | |
545 | for file in self._files: | |
546 | currModel._files.append(ProjectFile(file)) | |
547 | return currModel | |
548 | ||
549 |