ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/ns_dev/Python/NinoCode/Active_prgs/MCP/Trunk/MCP_Lib.py
Revision: 453
Committed: Wed Sep 11 17:59:42 2013 UTC (12 years, 6 months ago) by nino.borges
Content type: text/x-python
Original Path: Python/NinoCode/Active_prgs/MCP/MCP_Lib.py
File size: 45819 byte(s)
Log Message:
Added support for the working folder, IDS and made expedat library encrypted.  Also fixed a bug where it would error out if copy up was less than 1k.

File Contents

# User Rev Content
1 ninoborges 8 """
2    
3     MCP_Lib
4    
5     Created by
6     Emanuel Borges
7     10.25.2010
8    
9     This wil be the main library for the MCP aplications. Shared methods will be
10     kept here. Version informaiton for the entire MCP program will be kept here to.
11    
12     """
13    
14 nino.borges 321 import os,sys, win32com.client,subprocess,ftplib,NinoGenTools, win32com.decimal_23
15 ninoborges 8
16     def GetCaseList(sys_Overwrite ="", accessConnectionObj = None):
17 nino.borges 189 """ Main method to parse and return usable lists of cases. returns list of my cases, office cases and all cases.
18     also returns the cases directory."""
19 ninoborges 8 #print os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),"settings.sys")
20     if sys_Overwrite:
21     casesDir = open(os.path.join(sys_Overwrite,"settings.sys")).readline().replace("\n","")
22     else:
23     casesDir = open(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),"settings.sys")).readline().replace("\n","")
24     #casesDir = r"C:\Documents and Settings\eborges\My Documents\My Dropbox\Documents\Cases"
25     responsibleCases = []
26 nino.borges 189 officeCases = []
27     allCases = []
28     tPMName,tPMID,nul = GetTPMInfo()
29     if accessConnectionObj:
30     accessDB = accessConnectionObj
31     else:
32     print "connecting to matter tracking access db..."
33     ## Production version
34     accessDB = AccessDBConnection(r"\\chiads01\app\DS_CaseTrack\TPM_CaseTracking.mdb")
35    
36     ## Testing version
37     #accessDB = AccessDBConnection(r"W:\Manny\testing\TPM_CaseTracking.mdb")
38     print "connected to DB."
39     officeList = GetFullOfficeList()
40    
41     cliMatList = []
42     for office in officeList:
43     cliMatList.extend(accessDB.RetrieveOfficeCaseList(office))
44     cliMatList.sort()
45     for cliMat in cliMatList:
46     caseName = accessDB.GetCaseName(cliMat)
47     allCases.append('%s_(%s)'%(caseName,cliMat))
48    
49 ninoborges 8 if tPMName == 'ANALYST':
50     casesDir = None
51 nino.borges 189 officeCases = allCases
52     responsibleCases = allCases
53 ninoborges 8 else:
54 nino.borges 189 myMatterList = accessDB.RetrieveMyCaseList(tPMID)
55 ninoborges 8 for file in os.listdir(casesDir):
56     if os.path.isdir(os.path.join(casesDir,file)):
57     if file == "_Template_":
58     pass
59     elif file == "zzzz_dormant_":
60     pass
61     else:
62 nino.borges 189 officeCases.append(file)
63     ## if the case's matter is in my matter list, also append to responsibleCases
64     clientMatter = file.split("_(")[1]
65     clientMatter = clientMatter[:-1]
66     clientMatter = clientMatter.replace('-','.')
67     if clientMatter in myMatterList:
68     responsibleCases.append(file)
69     return responsibleCases, officeCases, allCases, casesDir
70 ninoborges 8
71     def GetTPMInfo(sys_Overwrite = ""):
72     """ Main method to parse and return the TMP and the Employee ID"""
73     if sys_Overwrite:
74     syscaseDir,tPMName, tPMID,office = open(os.path.join(sys_Overwrite,"settings.sys")).readlines()
75     else:
76     syscaseDir,tPMName, tPMID,office = open(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),"settings.sys")).readlines()
77    
78     #syscaseDir,tPMName, tPMID = open(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),"settings.sys")).readlines()
79     tPMName = tPMName.replace("\n","")
80     tPMID = tPMID.replace("\n","")
81     office = office.replace("\n","")
82     return tPMName, tPMID, office
83    
84     def GetFullOfficeList():
85     """Simply returns a list of all of the offices."""
86     officeList = ['Boston','Brussels','Chicago','Huston','London','Los Angeles','Miami','Moscow','Munich','New York',
87     'Orange County','Rome','San Diego','Silicon Valley','Washington, D.C.']
88     return officeList
89    
90     def GetOtherCaseFolder(office):
91     """This method will return the case folder for cases that you dont own"""
92     ## So this is in two places that I now have to maintian... not sure I like that.
93     caseFolderMatrix={'Boston':r"\\bstads01\app\Manny\Cases",
94     'Chicago':r"\\chiads01\data\CLI\Litigation_Support\MCP\Cases",
95     'Los Angeles':r"\\lasads01\data\Cli\_Lit_Support\MCP",
96     'New York':r"\\nykads01\data\cli\LitSupport\MCP\Cases",
97     'Miami':r"\\nykads01\data\cli\LitSupport\MCP\Cases",
98     'Orange County':r"\\lasads01\data\Cli\_Lit_Support\MCP",
99     'San Diego':r"\\lasads01\data\Cli\_Lit_Support\MCP",
100     'Silicon Valley':r"\\lasads01\data\Cli\_Lit_Support\MCP",
101     'Washington, D.C.':r"\\wdcads01\data\Cli\_MCP\Cases"}
102     try:
103     location = caseFolderMatrix[office]
104     except:
105     location = None
106     return location
107    
108 nino.borges 266 def GetArchiveFileTypeList():
109     """Returns a list of extensions of archive type files"""
110     return [".ZIP", ".RAR",".TAR",".7Z"]
111    
112 ninoborges 8 def GetMCPVersion():
113     """Returns the current version of the entire MCP program set"""
114 nino.borges 303 return 'v 1.8.0'
115 ninoborges 8
116    
117     class AccessDBConnection:
118     def __init__(self, accessDB):
119     daoEngine = win32com.client.Dispatch('DAO.DBEngine.36')
120     self.daoDB = daoEngine.OpenDatabase(accessDB)
121    
122     def MakeNewRSConnection(self, table, specialSelect = "*", specialWhere="" ):
123     """ This method will make a new RS connection for either reading or writing."""
124     if specialWhere:
125     statement = "SELECT %s FROM %s WHERE %s"%(specialSelect,table, specialWhere)
126     else:
127     statement = "SELECT %s FROM %s"%(specialSelect,table)
128     daoRSObj = self.daoDB.OpenRecordset(statement)
129     return daoRSObj
130    
131     def CloseAccessConnection(self):
132     """This closes the entire connection and not just the RS"""
133     self.daoDB.Close()
134    
135     def RetrieveAllCaseList(self):
136     """Retrieves all of the cases in the database regardless of assignment.(client matter list)"""
137     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData')
138     daoRSObj.MoveLast()
139     fullCount = daoRSObj.RecordCount
140     daoRSObj.MoveFirst()
141    
142     accessDBCLMList = []
143     for i in range(fullCount):
144     accessDBCLMList.append(daoRSObj.Fields('ClientMatterNum').Value)
145     daoRSObj.MoveNext()
146     daoRSObj.Close()
147     return accessDBCLMList
148    
149     def RetrieveMyCaseList(self, empID):
150     """Retrieves just 1 employees case list (client matter list)"""
151     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "empID = '%s'"%empID)
152     daoRSObj.MoveLast()
153     fullCount = daoRSObj.RecordCount
154     daoRSObj.MoveFirst()
155    
156     accessDBCLMList = []
157     for i in range(fullCount):
158     accessDBCLMList.append(daoRSObj.Fields('ClientMatterNum').Value)
159     daoRSObj.MoveNext()
160     daoRSObj.Close()
161     return accessDBCLMList
162    
163     def RetrieveOfficeCaseList(self, primaryOffice):
164     """Retrieves the case list for an entire office. Note, a case can be owned by a TPM in another office but
165     the primary office might still be an office that that TPM does not work for. Also people are not always
166     good about updating the primary office...(client matter list)"""
167     accessDBCLMList = []
168     try:
169     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "PrimaryOffice = '%s'"%primaryOffice)
170     daoRSObj.MoveLast()
171     fullCount = daoRSObj.RecordCount
172     daoRSObj.MoveFirst()
173    
174    
175     for i in range(fullCount):
176     accessDBCLMList.append(daoRSObj.Fields('ClientMatterNum').Value)
177     daoRSObj.MoveNext()
178     daoRSObj.Close()
179     except:
180     pass
181     return accessDBCLMList
182    
183     def RetrieveProductionsByCLM(self,CLM):
184     """This will retrieve a FULL production matrix for a specific clm"""
185     daoRSObj = self.MakeNewRSConnection('Tbl_MatterProductionDetail',
186 nino.borges 321 "ProductionID,ProductionComplDate, BegBates,EndBates,ProdDocCount,ProdPageCount,Notes,ProducedTo,ProductionMedia,ProductionSource,RequestedBy,ProductionDate,ProductionMediaPassword",
187 ninoborges 8 specialWhere = "ClientMatterNum='%s' ORDER BY ProductionComplDate"%CLM)
188     try:
189     ## Getting an exception that I cant capture when table is empty.
190     ## this will test and return empty if empty, until I can figure out a better test.
191     daoRSObj.MoveLast()
192     tableHasData = True
193     except:
194     tableHasData = False
195     productionList = []
196 nino.borges 321 productionMatrix = {}
197 ninoborges 8 if tableHasData:
198     fullCount = daoRSObj.RecordCount
199     daoRSObj.MoveFirst()
200     for i in range(fullCount):
201     try:
202     pgCount = str(int(daoRSObj.Fields('ProdPageCount').Value))
203     except:
204     pgCount = '0'
205     try:
206     docCount = str(int(daoRSObj.Fields('ProdDocCount').Value))
207     except:
208     docCount = '0'
209 nino.borges 321 grouping = str(daoRSObj.Fields('ProducedTo').Value)
210     if grouping:
211     pass
212     else:
213     grouping = 'default'
214     if grouping in productionMatrix.keys():
215     productionMatrix[grouping].append((str(daoRSObj.Fields('ProductionID').Value),
216 ninoborges 8 str(daoRSObj.Fields('ProductionComplDate').Value).split(' ')[0],
217 nino.borges 321 str(daoRSObj.Fields('ProductionDate').Value).split(' ')[0],
218 ninoborges 8 str(daoRSObj.Fields('BegBates').Value),str(daoRSObj.Fields('EndBates').Value),
219     docCount,pgCount,
220 nino.borges 321 str(daoRSObj.Fields('ProducedTo').Value),
221     str(daoRSObj.Fields('RequestedBy').Value),
222     str(daoRSObj.Fields('ProductionMedia').Value),
223     str(daoRSObj.Fields('ProductionMediaPassword').Value),
224     str(daoRSObj.Fields('ProductionSource').Value),
225 ninoborges 8 str(daoRSObj.Fields('Notes').Value)))
226 nino.borges 321 else:
227     productionMatrix[grouping] = [(str(daoRSObj.Fields('ProductionID').Value),
228     str(daoRSObj.Fields('ProductionComplDate').Value).split(' ')[0],
229     str(daoRSObj.Fields('ProductionDate').Value).split(' ')[0],
230     str(daoRSObj.Fields('BegBates').Value),str(daoRSObj.Fields('EndBates').Value),
231     docCount,pgCount,
232     str(daoRSObj.Fields('ProducedTo').Value),
233     str(daoRSObj.Fields('RequestedBy').Value),
234     str(daoRSObj.Fields('ProductionMedia').Value),
235     str(daoRSObj.Fields('ProductionMediaPassword').Value),
236     str(daoRSObj.Fields('ProductionSource').Value),
237     str(daoRSObj.Fields('Notes').Value))]
238     #productionList.append((str(daoRSObj.Fields('ProductionID').Value),
239     # str(daoRSObj.Fields('ProductionComplDate').Value).split(' ')[0],
240     # str(daoRSObj.Fields('BegBates').Value),str(daoRSObj.Fields('EndBates').Value),
241     # docCount,pgCount,
242     # str(daoRSObj.Fields('Notes').Value)))
243 ninoborges 8 daoRSObj.MoveNext()
244 nino.borges 321 #print len(productionList)
245 ninoborges 8 daoRSObj.Close()
246 nino.borges 321 return productionMatrix
247 ninoborges 8
248    
249     def RetrieveUploadsByCLM(self, CLM):
250     """This will retrieve a FULL upload matrix for a specific clm. This wil also pick the best Size (gb,mb,kb), since it's just for display."""
251     daoRSObj = self.MakeNewRSConnection('tbl_ClientDataQuantity',
252     "UEPOCH,ReviewPlatform,DataLoadDate,DataLoadedGB,DataLoadedMB,DataLoadedKB",
253     specialWhere = "ClientMatterNum='%s'"%CLM)
254     try:
255     ## Getting an exception that I cant capture when table is empty.
256     ## this will test and return empty if empty, until I can figure out a better test.
257     daoRSObj.MoveLast()
258     tableHasData = True
259     except:
260     tableHasData = False
261     caseUploadList = []
262     if tableHasData:
263     fullCount = daoRSObj.RecordCount
264     daoRSObj.MoveFirst()
265    
266     for i in range(fullCount):
267     if daoRSObj.Fields('DataLoadedKB').Value:
268     size = str(daoRSObj.Fields('DataLoadedKB').Value) + ' KB'
269     elif daoRSObj.Fields('DataLoadedMB').Value:
270     size = str(daoRSObj.Fields('DataLoadedMB').Value) + ' MB'
271     else:
272     size = str(daoRSObj.Fields('DataLoadedGB').Value) + ' GB'
273    
274     caseUploadList.append((str(daoRSObj.Fields('UEPOCH').Value),daoRSObj.Fields('ReviewPlatform').Value,
275     str(daoRSObj.Fields('DataLoadDate').Value).split(' ')[0],size))
276     daoRSObj.MoveNext()
277     daoRSObj.Close()
278     return caseUploadList
279    
280     def RetrieveOfficeUploads(self, primaryOffice):
281     """This only returns a matrix of clm{[EPOCH]}, since there isnt a reason to sync uploads from access"""
282     myClientMatterList = self.RetrieveOfficeCaseList(primaryOffice)
283     daoRSObj = self.MakeNewRSConnection('tbl_ClientDataQuantity')
284     daoRSObj.MoveLast()
285     fullCount = daoRSObj.RecordCount
286     daoRSObj.MoveFirst()
287    
288     caseUploadMatrix = {}
289     for i in range(fullCount):
290     currentClientMatter = daoRSObj.Fields('ClientMatterNum').Value
291     if currentClientMatter in myClientMatterList:
292     epoch = str(daoRSObj.Fields('UEPOCH').Value)
293     try:
294     caseUploadMatrix[currentClientMatter].append(epoch)
295     except:
296     caseUploadMatrix[currentClientMatter] = [epoch]
297     daoRSObj.MoveNext()
298     daoRSObj.Close()
299     return caseUploadMatrix
300    
301     def RetrieveMyCaseUploads(self,empID):
302     """This only returns a matrix of clm{[EPOCH]}, since there isnt a reason to sync uploads from access"""
303     myClientMatterList = self.RetrieveMyCaseList(empID)
304     daoRSObj = self.MakeNewRSConnection('tbl_ClientDataQuantity')
305     daoRSObj.MoveLast()
306     fullCount = daoRSObj.RecordCount
307     daoRSObj.MoveFirst()
308    
309     caseUploadMatrix = {}
310     for i in range(fullCount):
311     currentClientMatter = daoRSObj.Fields('ClientMatterNum').Value
312     if currentClientMatter in myClientMatterList:
313     epoch = daoRSObj.Fields('UEPOCH').Value
314     if epoch:
315     epoch = str(epoch)
316     if '.' in epoch:
317     epoch = epoch.split('.')[0]
318    
319     try:
320     caseUploadMatrix[currentClientMatter].append(epoch)
321     except:
322     caseUploadMatrix[currentClientMatter] = [epoch]
323     #loadedDate = daoRSObj.Fields('DataLoadDate').Value
324     #loadedDate = str(loadedDate.Format('%Y%m%d'))
325     #loadedSize =daoRSObj.Fields('DataLoadedGB').Value
326     #loadedSizeType = " GB"
327     #
328     #if loadedSize:
329     # ## If the GB loaded size exists, use that.
330     # pass
331     #else:
332     # ## if it does not, use the MB loaded field.
333     # loadedSize =daoRSObj.Fields('DataLoadedMB').Value
334     # loadedSizeType = " MB"
335     #loadedSize = str(loadedSize)
336     #if "." in loadedSize:
337     # loadedSize = loadedSize[:loadedSize.index('.')+3]
338     #try:
339     # caseUploadMatrix[currentClientMatter].append((loadedDate,loadedSize+loadedSizeType))
340     #except:
341     # caseUploadMatrix[currentClientMatter] = [(loadedDate,loadedSize+loadedSizeType)]
342     daoRSObj.MoveNext()
343     daoRSObj.Close()
344     return caseUploadMatrix
345    
346     def AddNewCase(self, caseName, CLM, TPM_Name, empID, chargable = False, reviewPlatform = "", responsibleVendor = "", responsibleOffice = ""):
347     """Adds a new case in the access DB."""
348     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData')
349     daoRSObj.AddNew()
350     daoRSObj.Fields('ClientMatterNum').Value = CLM
351     daoRSObj.Fields('CaseName').Value = caseName
352     daoRSObj.Fields('EmpID').Value = empID
353     daoRSObj.Fields('TPM').Value = TPM_Name
354     daoRSObj.Fields('PrimaryOffice').Value = responsibleOffice
355     daoRSObj.Update()
356     daoRSObj.Close()
357    
358     ## Per aaron, add to two other tables
359     clientNumber = CLM.split('.')[0]
360     daoRSObj = self.MakeNewRSConnection('tbl_Ref_Client')
361     try:
362     daoRSObj.AddNew()
363     daoRSObj.Fields('ClientNum').Value = clientNumber
364     daoRSObj.Update()
365     except:
366     pass
367     daoRSObj.Close()
368    
369     daoRSObj = self.MakeNewRSConnection('tbl_Ref_ClientMatter')
370     try:
371     daoRSObj.AddNew()
372     daoRSObj.Fields('ClientNum').Value = clientNumber
373     daoRSObj.Fields('ClientMatterNum').Value = CLM
374     daoRSObj.Update()
375     except:
376     pass
377     daoRSObj.Close()
378    
379     ## These below make their own record sets.
380     if chargable:
381     ## change this one aaron adds it.
382     pass
383     if reviewPlatform:
384     self.UpdateReviewPlatform(CLM, reviewPlatform)
385     if responsibleVendor:
386     self.UpdateResponsibleVendor(CLM,responsibleVendor)
387    
388    
389    
390     def UpdateChargable(self, CLM, chargable):
391     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
392     daoRSObj.Edit()
393     daoRSObj.Fields('BillableMatter').Value = chargable
394     daoRSObj.Update()
395     daoRSObj.Close()
396    
397     def GetChargable(self,CLM):
398     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
399     chargable = daoRSObj.Fields('BillableMatter').Value
400     daoRSObj.Close()
401     return chargable
402 nino.borges 321
403     def UpdateDisclosureLetter(self,CLM, letterSaved, pathToLetter):
404     """Allows you to check or uncheck the state of the disclosure letter and the link to it."""
405     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
406     daoRSObj.Edit()
407     daoRSObj.Fields('DisclosureLetterSaved').Value = letterSaved
408     daoRSObj.Fields('LinktoDisclosureLetter').Value = pathToLetter
409     daoRSObj.Update()
410     daoRSObj.Close()
411 ninoborges 8
412 nino.borges 321 def GetDisclosureLetter(self, CLM):
413     """Returns the state of the saved letter and the path to the disclosure letter"""
414     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
415     letterSaved = daoRSObj.Fields('DisclosureLetterSaved').Value
416     pathToLetter = daoRSObj.Fields('LinktoDisclosureLetter').Value
417     #pathToLetter = "foo"
418     #print letterSaved
419     daoRSObj.Close()
420     return letterSaved,pathToLetter
421    
422 ninoborges 8 def UpdateReviewPlatform(self, CLM, reviewPlatform):
423     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
424     daoRSObj.Edit()
425     daoRSObj.Fields('ReviewPlatform').Value = reviewPlatform
426     daoRSObj.Update()
427     daoRSObj.Close()
428    
429     def GetReviewPlatform(self,CLM):
430     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
431     platform = daoRSObj.Fields('ReviewPlatform').Value
432     daoRSObj.Close()
433     return platform
434    
435     def UpdateResponsibleVendors(self, CLM,responsibleVendorTpl):
436     """VendorTpl should be a tuple of (processing,scanning,hosting) with None if you dont have it"""
437     processingVendor, scanningVendor, hostingVendor = responsibleVendorTpl
438     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
439     if processingVendor:
440     daoRSObj.Edit()
441     daoRSObj.Fields('ProcessingVendor').Value = processingVendor
442     daoRSObj.Update()
443     if scanningVendor:
444     daoRSObj.Edit()
445     daoRSObj.Fields('ScanningVendor').Value = scanningVendor
446     daoRSObj.Update()
447     if hostingVendor:
448     daoRSObj.Edit()
449     daoRSObj.Fields('HostingVendor').Value = hostingVendor
450     daoRSObj.Update()
451     daoRSObj.Close()
452    
453     def GetResponsibleVendorTpl(self, CLM):
454     """Returns a tuple of (processing,scanning,hosting) with None if you dont have it"""
455     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
456     processingVendor = daoRSObj.Fields('ProcessingVendor').Value
457     scanningVendor = daoRSObj.Fields('ScanningVendor').Value
458     hostingVendor = daoRSObj.Fields('HostingVendor').Value
459     daoRSObj.Close()
460     tmpTpl = (processingVendor,scanningVendor,hostingVendor)
461     return tmpTpl
462    
463     def UpdateCaseUpload(self, CLM, reviewPlatform, uploadMatrix):
464     """Format for matrix is epoch is key and uploads are in a tpl. (12/23/2010,49MB) Date format is mm/dd/yyyy"""
465     daoRSObj = self.MakeNewRSConnection('tbl_ClientDataQuantity')
466    
467     ## Dont for get to convert the date first somewhere.
468     for i in uploadMatrix.keys():
469     (date, size) = uploadMatrix[i]
470     daoRSObj.AddNew()
471     daoRSObj.Fields('ClientMatterNum').Value = CLM
472     daoRSObj.Fields('UEPOCH').Value = i
473     daoRSObj.Fields('DataLoadDate').Value = date
474     daoRSObj.Fields('ReviewPlatform').Value = reviewPlatform
475 nino.borges 453
476 ninoborges 8 if "GB" in size:
477     daoRSObj.Fields('dataLoadedGB').Value = float(size.replace("GB",""))
478     elif "MB" in size:
479     daoRSObj.Fields('dataLoadedMB').Value = float(size.replace("MB",""))
480     else:
481 nino.borges 453 if "bytes" in size:
482     size = "1 KB"
483 ninoborges 8 daoRSObj.Fields('DataLoadedKB').Value = float(size.replace("KB",""))
484     daoRSObj.Update()
485     daoRSObj.Close()
486    
487     def DeleteCaseUpload(self,CLM,UEPOCH):
488     """This method will let you delete a single case upload but only if it was added by the MCP.
489     i.e has a UEPOCH"""
490     ## When calling UEPOCHs, dont put it in a ''
491     daoRSObj = self.MakeNewRSConnection('tbl_ClientDataQuantity', specialWhere = "UEPOCH=%s"%UEPOCH)
492     ## WHERE AND is not working so I'm going to have to WHERE for the UEPOCH and then do a quick search for the CLM, to be safe.
493     daoRSObj.MoveLast()
494     recordCount = daoRSObj.RecordCount
495     daoRSObj.MoveFirst()
496     ## This wont allow you to delete if there are multiple records with same UEPOCH
497     if recordCount == 1:
498     val2 = daoRSObj.Fields('ClientMatterNum').Value
499     if val2 == CLM:
500     daoRSObj.Delete()
501     errorRpt = False
502     else:
503     errorRpt = True
504     else:
505     errorRpt = True
506     daoRSObj.Close()
507     #print errorRpt
508     return errorRpt
509 nino.borges 321
510     def GetProducedToEntities(self,CLM):
511     """This will return, for a specific matter, a list of the current 'produced to' options, as kind of a history. """
512     daoRSObj = self.MakeNewRSConnection('Tbl_MatterProductionDetail',
513     specialWhere = "ClientMatterNum='%s'"%CLM)
514     prodToList = []
515     try:
516     daoRSObj.MoveLast()
517     tableHasData = True
518     except:
519     tableHasData = False
520     productionMatrix = {}
521     if tableHasData:
522     fullCount = daoRSObj.RecordCount
523     daoRSObj.MoveFirst()
524     for i in range(fullCount):
525     if daoRSObj.Fields('ProducedTo').Value:
526     productionMatrix[daoRSObj.Fields('ProducedTo').Value] = 1
527     daoRSObj.MoveNext()
528     prodToList = productionMatrix.keys()
529     daoRSObj.Close()
530     return prodToList
531    
532     def GetProductionRequestedByNames(self,CLM):
533     """This will return, for a specific matter, a list of the current 'production requested by names, as kind of a history. """
534     daoRSObj = self.MakeNewRSConnection('Tbl_MatterProductionDetail',
535     specialWhere = "ClientMatterNum='%s'"%CLM)
536     reqByList = []
537     try:
538     daoRSObj.MoveLast()
539     tableHasData = True
540     except:
541     tableHasData = False
542     reqByMatrix = {}
543     if tableHasData:
544     fullCount = daoRSObj.RecordCount
545     daoRSObj.MoveFirst()
546     for i in range(fullCount):
547     if daoRSObj.Fields('RequestedBy').Value:
548     reqByMatrix[daoRSObj.Fields('RequestedBy').Value] = 1
549     daoRSObj.MoveNext()
550     reqByList = reqByMatrix.keys()
551     daoRSObj.Close()
552     return reqByList
553 ninoborges 8
554 nino.borges 321 def UpdateProductionDetail(self, CLM, prodID, prodProcessedDate, begBates,endBates,prodDocCount, prodPageCount, prodNotes, prodTo, prodMedia,prodSource,prodReqBy,prodSentDate,prodMediaPassword):
555 ninoborges 8 """This method will let you add an entire produciton record to the production table. All fields are manadatory.
556     the date is in mm/dd/yyyy format."""
557     try:
558     testdaoRSObj = self.MakeNewRSConnection('Tbl_MatterProductionDetail', specialSelect ="ProductionID",specialWhere = "ClientMatterNum='%s'"%CLM)
559     testdaoRSObj.MoveLast()
560     testRecordCount = testdaoRSObj.RecordCount
561     testdaoRSObj.MoveFirst()
562     prodList = []
563     if testRecordCount:
564     for i in range(testRecordCount):
565     prodList.append(testdaoRSObj.Fields('ProductionID').Value)
566     testdaoRSObj.MoveNext()
567     testdaoRSObj.Close()
568     #print testRecordCount
569     #print prodList
570     if prodID in prodList:
571     prodIncrement = NinoGenTools.Counter(1)
572     prodID = prodID+ "_"+"%0*d"%(4,prodIncrement.count)
573     prodIncrement.inc()
574     while prodID in prodList:
575     prodID = prodID[:-4] +"%0*d"%(4,prodIncrement.count)
576     prodIncrement.inc()
577     except:
578     pass
579    
580     daoRSObj = self.MakeNewRSConnection('Tbl_MatterProductionDetail')
581     daoRSObj.AddNew()
582     daoRSObj.Fields('ClientMatterNum').Value = CLM
583     daoRSObj.Fields('ProductionID').Value = prodID
584 nino.borges 321 daoRSObj.Fields('ProductionComplDate').Value = prodProcessedDate
585 ninoborges 8 daoRSObj.Fields('BegBates').Value = begBates
586     daoRSObj.Fields('EndBates').Value = endBates
587     daoRSObj.Fields('ProdDocCount').Value = prodDocCount
588     daoRSObj.Fields('ProdPageCount').Value = prodPageCount
589     daoRSObj.Fields('Notes').Value = prodNotes
590 nino.borges 321 daoRSObj.Fields('ProducedTo').Value =prodTo
591     daoRSObj.Fields('ProductionMedia').Value =prodMedia
592     daoRSObj.Fields('ProductionSource').Value =prodSource
593     daoRSObj.Fields('RequestedBy').Value =prodReqBy
594     daoRSObj.Fields('ProductionDate').Value =prodSentDate
595     daoRSObj.Fields('ProductionMediaPassword').Value =prodMediaPassword
596 ninoborges 8
597     daoRSObj.Update()
598     daoRSObj.Close()
599    
600     def UpdateResponsibleAttorney(self, CLM, responsibleAttny):
601     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
602     daoRSObj.Edit()
603     daoRSObj.Fields('PrimaryAttorneyContact').Value = responsibleAttny
604     daoRSObj.Update()
605     daoRSObj.Close()
606    
607     def GetResponsibleAttorney(self, CLM):
608     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
609     val = daoRSObj.Fields('PrimaryAttorneyContact').Value
610     daoRSObj.Close()
611     return val
612    
613     def UpdateOtherAttorneys(self,CLM, otherAttorneysList):
614     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
615     daoRSObj.Edit()
616     ## add this when aaron adds it.
617     daoRSObj.Update()
618     daoRSObj.Close()
619    
620     def UpdateResponsibleParalegal(self,CLM, responsibleParalegal):
621     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
622     daoRSObj.Edit()
623     daoRSObj.Fields('ParalegalContact').Value = responsibleParalegal
624     daoRSObj.Update()
625     daoRSObj.Close()
626    
627     def GetResponsibleParalegal(self,CLM):
628     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
629     val = daoRSObj.Fields('ParalegalContact').Value
630     daoRSObj.Close()
631     return val
632    
633     def UpdatePrimaryOffice(self,CLM, primaryOffice):
634     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
635     daoRSObj.Edit()
636     daoRSObj.Fields('PrimaryOffice').Value = primaryOffice
637     daoRSObj.Update()
638     daoRSObj.Close()
639    
640     def GetPrimaryOffice(self,CLM):
641     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
642     val = daoRSObj.Fields('PrimaryOffice').Value
643     daoRSObj.Close()
644     return val
645    
646     def UpdateResponsibleTPM(self, CLM, tPMName):
647     """Format should be last, first"""
648     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
649     daoRSObj.Edit()
650     daoRSObj.Fields('TPM').Value = tPMName
651     daoRSObj.Update()
652     daoRSObj.Close()
653    
654     def GetResponsibleTPM(self,CLM):
655     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
656     val = daoRSObj.Fields('TPM').Value
657     daoRSObj.Close()
658     return val
659    
660     def GetCaseStatus(self,CLM):
661     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
662     val = daoRSObj.Fields('ProjectStatus').Value
663     daoRSObj.Close()
664     return val
665    
666     def UpdateCaseStatus(self,CLM,status):
667     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
668     daoRSObj.Edit()
669     daoRSObj.Fields('ProjectStatus').Value = status
670     daoRSObj.Update()
671     daoRSObj.Close()
672    
673     def GetCaseName(self,CLM):
674     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
675     val = daoRSObj.Fields('CaseName').Value
676     daoRSObj.Close()
677     return val
678    
679     def UpdateCaseName(self,CLM,caseName):
680     """This is just the internal name for the case"""
681     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
682     daoRSObj.Edit()
683     daoRSObj.Fields('CaseName').Value = caseName
684     daoRSObj.Update()
685     daoRSObj.Close()
686 nino.borges 343
687     def UpdateClientMatterNum(self,oldCLM,newCLM):
688     """Changes the client matter number for a case"""
689     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%oldCLM)
690     daoRSObj.Edit()
691     daoRSObj.Fields('ClientMatterNum').Value = newCLM
692     daoRSObj.Update()
693     daoRSObj.Close()
694 ninoborges 8
695 nino.borges 232 def GetAlternateMediaPath(self,CLM):
696     """Returns the alternate media path"""
697     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
698     val = daoRSObj.Fields('AlternateMediaPath').Value
699     daoRSObj.Close()
700     return val
701    
702     def UpdateAlternateMediaPath(self,CLM,alternateMediaPath):
703     """Updates the alternate Media Path in the db"""
704     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
705     daoRSObj.Edit()
706     daoRSObj.Fields('AlternateMediaPath').Value = alternateMediaPath
707     daoRSObj.Update()
708     daoRSObj.Close()
709    
710     def GetVendorFolderPath(self,CLM):
711     """Returns the vendor Folder path"""
712     try:
713     daoRSObj = self.MakeNewRSConnection('tbl_VendorFolderPath', specialWhere = "ClientMatterNum='%s'"%CLM)
714     val = daoRSObj.Fields('VendorFolderPath').Value
715     daoRSObj.Close()
716     except:
717     val = None
718     return val
719    
720     def UpdateVendorFolderPath(self,CLM,vendorFolderPath):
721     """Updates the Vendor Folder Path in the db"""
722 nino.borges 303 #print vendorFolderPath
723     try:
724     daoRSObj = self.MakeNewRSConnection('tbl_VendorFolderPath', specialWhere = "ClientMatterNum='%s'"%CLM)
725     daoRSObj.Edit()
726     except:
727     daoRSObj = self.MakeNewRSConnection('tbl_VendorFolderPath')
728     daoRSObj.Edit()
729     daoRSObj.Fields('ClientMatterNum').Value = CLM
730 nino.borges 232 daoRSObj.Fields('VendorFolderPath').Value = vendorFolderPath
731     daoRSObj.Update()
732     daoRSObj.Close()
733 nino.borges 303
734     def GetUploadCostRate(self,CLM):
735     """Returns the upload cost for a case"""
736     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
737     val = daoRSObj.Fields('UploadCost_GB').Value
738     daoRSObj.Close()
739     return val
740 nino.borges 232
741 nino.borges 303 def UpdateUploadCostRate(self,CLM, uploadCost):
742     """Updates the upload cost for a case"""
743     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
744     daoRSObj.Edit()
745     daoRSObj.Fields('UploadCost_GB').Value = uploadCost
746     daoRSObj.Update()
747     daoRSObj.Close()
748    
749     def GetStorageCostRate(self,CLM):
750     """Returns the Storage cost for a case"""
751     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
752     val = daoRSObj.Fields('StorageCost_GB').Value
753     daoRSObj.Close()
754     return val
755    
756     def UpdateStorageCostRate(self,CLM, storageCost):
757     """Updates the upload cost for a case"""
758     daoRSObj = self.MakeNewRSConnection('tbl_MatterTrackingData', specialWhere = "ClientMatterNum='%s'"%CLM)
759     daoRSObj.Edit()
760     daoRSObj.Fields('StorageCost_GB').Value = storageCost
761     daoRSObj.Update()
762     daoRSObj.Close()
763    
764     def GetDefaultUploadCostRate(self, platform = "Relativity"):
765     """Returns the current default upload cost"""
766     if platform == "Relativity":
767     cost = "50"
768     else:
769     cost = "50"
770     return cost
771    
772     def GetDefaultStorageCostRate(self, platform = "Relativity"):
773     """Returns the current default storage cost"""
774     if platform == "Relativity":
775     cost = "20"
776     else:
777     cost = "20"
778     return cost
779    
780 ninoborges 8 class ExpeDatConnection:
781     def __init__(self, platform):
782     if platform == "Relativity":
783     self.initialPath = "Relativity"
784     #self.userName = "eborges"
785     else:
786     self.initialPath = "Concordance Data"
787     #self.userName = "eborgesc"
788    
789     self.userName = "eborges"
790 nino.borges 446 #self.hostName = "@mweftp.litigation.lexisnexis.com"
791 nino.borges 453 self.hostName = "@transfer.mcdermottdiscovery.com"
792 ninoborges 8 self.userPassword = "9atrEFeh"
793     #self.exeLocation = r"C:\Documents and Settings\eborges\My Documents\MyDownloads\ExpDat\movedat.exe"
794     self.exeLocation = r"C:\Program Files\ExpDat\movedat.exe"
795    
796 nino.borges 203 def ListDir(self,path):
797     """Returns the contents of a directory. returns files, dirs."""
798 nino.borges 453 print "debug: listing dir"
799 nino.borges 203 path = os.path.join(self.initialPath,path)
800 nino.borges 453 args = [self.exeLocation,"-K","%s:%s%s:%s"%(self.userName,self.userPassword,self.hostName,path)]
801 nino.borges 203 fnull = open(os.devnull, 'w')
802     process = subprocess.Popen(args,stdout = subprocess.PIPE, stderr = fnull)
803     rawFileList,errCode =process.communicate()
804     rawFileList = rawFileList.split("\n")
805     fileList = []
806     dirList = []
807     if rawFileList:
808     for i in rawFileList:
809     if i:
810     i = i.split(" ")[-1]
811     if i[-1] == "/":
812     dirList.append(i)
813     else:
814     fileList.append(i)
815     fnull.close()
816 nino.borges 453 print "debug: dir listed."
817 nino.borges 203 return fileList, dirList
818    
819     def GatherFullDirListMatrix(self,vendorFolder):
820     """Returns a matrix of a list path, with all the files and dirs in a vendor folder"""
821     fileList,dirList = self.ListDir(vendorFolder)
822     folderMatrix = []
823     currentPath = vendorFolder
824     for indFile in fileList:
825     folderMatrix.append(indFile)
826     #while dirList:
827     for dir in dirList:
828 nino.borges 232 #print dir
829 nino.borges 206 newPath = os.path.join(currentPath, dir)
830 nino.borges 203 print currentPath
831 nino.borges 206 subFileList,subDirList = self.ListDir(newPath)
832 nino.borges 203 newList = []
833     for indFile in subFileList:
834     newList.append(indFile)
835 nino.borges 232 #print indFile
836 nino.borges 203 folderMatrix.append([dir,newList])
837 nino.borges 232 #print folderMatrix
838 nino.borges 203 #while dirList:
839     return folderMatrix
840    
841 nino.borges 232 def GatherSize(self,path):
842     """Returns the size of a given path or archive"""
843     extension = os.path.splitext(path)[1]
844     path = os.path.join(self.initialPath,path)
845     #path = self.initialPath + "/" + path
846     if extension.upper() == '.ZIP':
847 nino.borges 453 args = [self.exeLocation,"-D","-K","%s:%s%s:%s=zipsize"%(self.userName,self.userPassword,self.hostName,path)]
848 nino.borges 232 fnull = open(os.devnull, 'w')
849     process = subprocess.Popen(args,stdout = subprocess.PIPE, stderr = fnull)
850     rawFileSize,errCode =process.communicate()
851     elif extension == "":
852 nino.borges 453 args = [self.exeLocation,"-K","%s:%s%s:%s=*lr"%(self.userName,self.userPassword,self.hostName,path)]
853 nino.borges 232 #print args
854     fnull = open(os.devnull, 'w')
855     process = subprocess.Popen(args,stdout = subprocess.PIPE, stderr = fnull)
856     rawDirList,errCode =process.communicate()
857     rawDirList = rawDirList.split("\n")
858     rawFileSize = 0
859     for line in rawDirList[1:]:
860 nino.borges 453 #print "Debug:" + line
861 nino.borges 232 if line:
862     size = line.split("\t")[1]
863     itemType = line.split("\t")[3]
864     if itemType == "F":
865     rawFileSize = rawFileSize + int(size,16)
866     else:
867 nino.borges 453 args = [self.exeLocation,"-K","%s:%s%s:%s=*ls"%(self.userName,self.userPassword,self.hostName,path)]
868 nino.borges 232 #print args
869     fnull = open(os.devnull, 'w')
870     process = subprocess.Popen(args,stdout = subprocess.PIPE, stderr = fnull)
871     rawDirList,errCode =process.communicate()
872 nino.borges 453 #print rawDirList
873     #outputFile = open(r"c:\test.txt",'w')
874     #outputFile.writelines(rawDirList)
875     #outputFile.close()
876    
877     rawDirList = rawDirList.split("\n")[1]
878     #print rawDirList
879 nino.borges 232 rawFileSize = 0
880     if rawDirList:
881 nino.borges 453 print "Debug:" + rawDirList
882 nino.borges 232 size = rawDirList.split("\t")[1]
883     rawFileSize = int(size,16)
884     fnull.close()
885     if rawFileSize:
886     print "size is %s"%rawFileSize
887     else:
888     rawFileSize = False
889 nino.borges 239 return rawFileSize
890 nino.borges 232
891 ninoborges 8 def TestPath(self,path):
892     """Tests to see if path already exists"""
893 nino.borges 453 #print "debug: Testing path"
894 ninoborges 8 path = os.path.join(self.initialPath,path)
895 nino.borges 453 args = [self.exeLocation,"-K","%s:%s%s:%s"%(self.userName,self.userPassword,self.hostName,path)]
896 nino.borges 232 #print args
897 ninoborges 8 fnull = open(os.devnull, 'w')
898     errCode = subprocess.call(args,stdout = fnull, stderr = fnull)
899     fnull.close()
900     if errCode == 0:
901     return True
902     if errCode == 25:
903     return False
904     else:
905     print "OTHER ERROR CODE %s. CALL MANNY!"%str(errCode)
906 nino.borges 453 #print "debug: Testing path done."
907 ninoborges 8
908     def CreateNewPath(self,path):
909     """Creates a new path on the LN system"""
910     path = os.path.join(self.initialPath,path)
911 nino.borges 453 #print "debug: creating new path %s"% path
912     args = [self.exeLocation,"-n","-K","%s:%s%s:%s"%(self.userName,self.userPassword,self.hostName,path)]
913 ninoborges 8 fnull = open(os.devnull, 'w')
914     errCode = subprocess.call(args,stdout = fnull, stderr = fnull)
915     fnull.close()
916     #return errCode
917     if errCode == 0:
918     return True
919     if errCode == 34:
920     ## Path already exists
921     return False
922     else:
923     print "OTHER ERROR CODE %s. CALL MANNY!"%str(errCode)
924 nino.borges 453 #print "debug: new path created."
925 nino.borges 203
926     def MoveOnLN(self,absSourcePathAndFile,targetDirAndFile):
927     """Performs a move from LN to LN"""
928     targetDirAndFile = os.path.join(self.initialPath,targetDirAndFile)
929 nino.borges 453 print targetDirAndFile
930 nino.borges 203 absSourcePathAndFile = os.path.join(self.initialPath,absSourcePathAndFile)
931 nino.borges 453 print absSourcePathAndFile
932 nino.borges 203 #targetDir = targetDir + "\\"
933 nino.borges 453 args = [self.exeLocation,"-m","-K","%s:%s%s:%s"%(self.userName,self.userPassword,self.hostName,absSourcePathAndFile),"%s"%targetDirAndFile]
934 nino.borges 203 fnull = open(os.devnull, 'w')
935     errCode = subprocess.call(args,stdout = fnull, stderr = fnull)
936     fnull.close()
937     #return errCode
938     if errCode == 0:
939     return True
940     if errCode == 34:
941     ## Path already exists
942     return False
943     else:
944     print "OTHER ERROR CODE %s. CALL MANNY!"%str(errCode)
945 ninoborges 8
946     def CopyToLN(self,absSourcePathAndFile,targetDir):
947     """copies absPath to LN. targetDir should be a dir not a file."""
948     ## Expedat requires that if it's a target dir, you end it in a trailing slash
949     targetDir = os.path.join(self.initialPath,targetDir)
950     targetDir = targetDir + "\\"
951 nino.borges 453 args = [self.exeLocation,"-K",absSourcePathAndFile,"%s:%s%s:%s"%(self.userName,self.userPassword,self.hostName,targetDir)]
952 ninoborges 8 fnull = open(os.devnull, 'w')
953     errCode = subprocess.call(args,stdout = fnull, stderr = fnull)
954     fnull.close()
955     #return errCode
956     if errCode == 0:
957     return True
958     if errCode == 25:
959     """The target path does not exist"""
960     return False
961     elif errCode == 29:
962     """The source file or path does not exist"""
963     return False
964     else:
965     print "OTHER ERROR CODE %s. CALL MANNY!"%str(errCode)
966    
967     class MweFtpConnection:
968     def __init__(self):
969     self.userName = "eborges"
970     self.hostName = "disftp.mwe.com"
971     self.userPassword = "rever78"
972     self.connection = ftplib.FTP_TLS(self.hostName)
973     self.connection.login(self.userName,self.userPassword)
974     self.connection.prot_p()
975    
976     def TestPath(self,path):
977     startDir = self.connection.pwd()
978     try:
979     self.connection.cwd(path)
980     sucess = True
981     except:
982     sucess = False
983     self.connection.cwd(startDir)
984     return sucess
985    
986     def CreateNewPath(self,path):
987     self.connection.mkd(path)
988    
989     def CopyToDis(self,absSourcePathAndFile,targetDir):
990     startDir = self.connection.pwd()
991     fileName = os.path.split(absSourcePathAndFile)[1]
992     self.connection.cwd(targetDir)
993     activePackage = open(absSourcePathAndFile,'rb')
994     self.connection.storbinary("STOR %s"%fileName,activePackage)
995     activePackage.close()
996     self.connection.cwd(startDir)
997    
998     def CloseConnection(self):
999     self.connection.close()