##// END OF EJS Templates
Miguel Valdez -
r681:a13b962c6023
parent child
Show More
@@ -0,0 +1,346
1 """The admin module contains all administrative classes relating to the schain python api.
2
3 The main role of this module is to send some reports. It contains a
4 notification class and a standard error handing class.
5
6 $Id: admin.py 3966 2015-12-01 14:32:29Z miguel.urco $
7 """
8 import os
9 import smtplib
10 import ConfigParser
11 import StringIO
12
13 from email.mime.text import MIMEText
14 from email.mime.application import MIMEApplication
15 from email.mime.multipart import MIMEMultipart
16
17 class SchainConfigure():
18
19 __DEFAULT_SENDER_EMAIL = "notifier-schain@jro.igp.gob.pe"
20 __DEFAULT_ADMINISTRATOR_EMAIL = "miguel.urco@jro.igp.gob.pe"
21 __DEFAULT_EMAIL_SERVER = "jro-zimbra.igp.gob.pe"
22
23 __SCHAIN_ADMINISTRATOR_EMAIL = "CONTACT"
24 __SCHAIN_EMAIL_SERVER = "MAILSERVER"
25 __SCHAIN_SENDER_EMAIL = "MAILSERVER_ACCOUNT"
26
27 def __init__(self, initFile = None):
28
29 # Set configuration file
30 if (initFile == None):
31 self.__confFilePath = "/etc/schain.conf"
32 else:
33 self.__confFilePath = initFile
34
35 # open configuration file
36 try:
37 self.__confFile = open(self.__confFilePath, "r")
38 except IOError:
39 # can't read from file - use all hard-coded values
40 self.__initFromHardCode()
41 return
42
43 # create Parser using standard module ConfigParser
44 self.__parser = ConfigParser.ConfigParser()
45
46 # read conf file into a StringIO with "[madrigal]\n" section heading prepended
47 strConfFile = StringIO.StringIO("[schain]\n" + self.__confFile.read())
48
49 # parse StringIO configuration file
50 self.__parser.readfp(strConfFile)
51
52 # read information from configuration file
53 self.__readConfFile()
54
55 # close conf file
56 self.__confFile.close()
57
58
59 def __initFromHardCode(self):
60
61 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
62 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
63 self.__email_server = self.__DEFAULT_EMAIL_SERVER
64
65 def __readConfFile(self):
66 """__readConfFile is a private helper function that reads information from the parsed config file.
67
68 Inputs: None
69
70 Returns: Void.
71
72 Affects: Initializes class member variables that are found in the config file.
73
74 Exceptions: MadrigalError thrown if any key not found.
75 """
76
77 # get the sender email
78 try:
79 self.__sender_email = self.__parser.get("schain", self.__SCHAIN_SENDER_EMAIL)
80 except:
81 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
82
83 # get the administrator email
84 try:
85 self.__admin_email = self.__parser.get("schain", self.__SCHAIN_ADMINISTRATOR_EMAIL)
86 except:
87 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
88
89 # get the server email
90 try:
91 self.__email_server = self.__parser.get("schain", self.__SCHAIN_EMAIL_SERVER)
92 except:
93 self.__email_server = self.__DEFAULT_EMAIL_SERVER
94
95 def getEmailServer(self):
96
97 return self.__email_server
98
99 def getSenderEmail(self):
100
101 return self.__sender_email
102
103 def getAdminEmail(self):
104
105 return self.__admin_email
106
107 class SchainNotify:
108 """SchainNotify is an object used to send messages to an administrator about a Schain software.
109
110 This object provides functions needed to send messages to an administrator about a Schain , for now
111 only sendAlert, which sends an email to the site administrator found is ADMIN_EMAIL
112
113 Usage example:
114
115 import schainpy.admin
116
117 try:
118
119 adminObj = schainpy.admin.SchainNotify()
120 adminObj.sendAlert('This is important!', 'Important Message')
121
122 except schainpy.admin.SchainError, e:
123
124 print e.getExceptionStr()
125
126
127 Non-standard Python modules used:
128 None
129
130 Exceptions thrown: None - Note that SchainNotify tries every trick it knows to avoid
131 throwing exceptions, since this is the class that will generally be called when there is a problem.
132
133 Change history:
134
135 Written by "Miguel Urco":mailto:miguel.urco@jro.igp.gob.pe Dec. 1, 2015
136 """
137
138 #constants
139
140 def __init__(self):
141 """__init__ initializes SchainNotify by getting some basic information from SchainDB and SchainSite.
142
143 Note that SchainNotify tries every trick it knows to avoid throwing exceptions, since
144 this is the class that will generally be called when there is a problem.
145
146 Inputs: Existing SchainDB object, by default = None.
147
148 Returns: void
149
150 Affects: Initializes self.__binDir.
151
152 Exceptions: None.
153 """
154
155 # note that the main configuration file is unavailable
156 # the best that can be done is send an email to root using localhost mailserver
157 confObj = SchainConfigure()
158
159 self.__emailFromAddress = confObj.getSenderEmail()
160 self.__emailToAddress = confObj.getAdminEmail()
161 self.__emailServer = confObj.getEmailServer()
162
163 def sendEmail(self, email_from, email_to, subject='Error running ...', message="", subtitle="", filename="", html_format=True):
164
165 msg = MIMEMultipart()
166 msg['Subject'] = subject
167 msg['From'] = "(Python SChain API): " + email_from
168 msg['Reply-to'] = email_from
169 msg['To'] = email_to
170
171 # That is what u see if dont have an email reader:
172 msg.preamble = 'SChainPy'
173
174 if html_format:
175 message = "<h1> %s </h1>" %subject + "<h3>" + subtitle.replace("\n", "</h3><h3>\n") + "</h3>" + message.replace("\n", "<br>\n")
176 message = "<html>\n" + message + '</html>'
177
178 # This is the textual part:
179 part = MIMEText(message, "html")
180 else:
181 message = subject + "\n" + subtitle + "\n" + message
182 part = MIMEText(message)
183
184 msg.attach(part)
185
186 if os.path.isfile(filename):
187 # This is the binary part(The Attachment):
188 part = MIMEApplication(open(filename,"rb").read())
189 part.add_header('Content-Disposition',
190 'attachment',
191 filename=os.path.basename(filename))
192 msg.attach(part)
193
194 # Create an instance in SMTP server
195 smtp = smtplib.SMTP(self.__emailServer)
196 # Start the server:
197 # smtp.ehlo()
198 # smtp.login(email_from, email_from_pass)
199
200 # Send the email
201 smtp.sendmail(msg['From'], msg['To'], msg.as_string())
202 smtp.quit()
203
204
205 def sendAlert(self, message, subject = "", subtitle="", filename=""):
206 """sendAlert sends an email with the given message and optional title.
207
208 Inputs: message (string), and optional title (string)
209
210 Returns: void
211
212 Affects: none
213
214 Exceptions: None.
215 """
216 print "***** Sending alert to %s *****" %self.__emailToAddress
217 # set up message
218
219 self.sendEmail(email_from=self.__emailFromAddress,
220 email_to=self.__emailToAddress,
221 subject=subject,
222 message=message,
223 subtitle=subtitle,
224 filename=filename)
225
226 print "***** Your system administrator has been notified *****"
227
228
229 def notify(self, email, message, subject = "", subtitle="", filename=""):
230 """notify sends an email with the given message and title to email.
231
232 Inputs: email (string), message (string), and subject (string)
233
234 Returns: void
235
236 Affects: none
237
238 Exceptions: None.
239 """
240
241 print "Notifying to %s ..." %email
242
243 self.sendEmail(email_from=self.__emailFromAddress,
244 email_to=email,
245 subject=subject,
246 message=message,
247 subtitle=subtitle,
248 filename=filename)
249
250 print "***** Your system administrator has been notified *****"
251
252 class SchainError:
253 """SchainError is an exception class that is thrown for all known errors in using Schain Py lib.
254
255 Usage example:
256
257 import sys, traceback
258 import schainpy.admin
259
260 try:
261
262 test = open('ImportantFile.txt', 'r')
263
264 except:
265
266 raise schainpy.admin.SchainError('ImportantFile.txt not opened!',
267 traceback.format_exception(sys.exc_info()[0],
268 sys.exc_info()[1],
269 sys.exc_info()[2]))
270 """
271
272
273 def __init__(self, strInterpretation, exceptionList):
274 """ __init__ gathers the interpretation string along with all information from sys.exc_info().
275
276 Inputs: strIntepretation - A string representing the programmer's interpretation of
277 why the exception occurred
278
279 exceptionList - a list of strings completely describing the exception.
280 Generated by traceback.format_exception(sys.exc_info()[0],
281 sys.exc_info()[1],
282 sys.exc_info()[2])
283
284 Returns: Void.
285
286 Affects: Initializes class member variables _strInterp, _strExcList.
287
288 Exceptions: None.
289 """
290
291 self._strInterp = strInterpretation
292 self._strExcList = exceptionList
293
294
295 def getExceptionStr(self):
296 """ getExceptionStr returns a formatted string ready for printing completely describing the exception.
297
298 Inputs: None
299
300 Returns: A formatted string ready for printing completely describing the exception.
301
302 Affects: None
303
304 Exceptions: None.
305 """
306 excStr = 'The following Schain Python exception has occurred:\n'
307 excStr = excStr + self._strInterp + '\n\n'
308
309 if self._strExcList != None:
310 for item in self._strExcList:
311 excStr = excStr + str(item) + '\n'
312
313 return excStr
314
315 def __str__(self):
316 return(self.getExceptionStr())
317
318
319 def getExceptionHtml(self):
320 """ getExceptionHtml returns an Html formatted string completely describing the exception.
321
322 Inputs: None
323
324 Returns: A formatted string ready for printing completely describing the exception.
325
326 Affects: None
327
328 Exceptions: None.
329 """
330
331 excStr = '<BR>The following Schain Python exception has occurred:\n<BR>'
332 excStr = excStr + self._strInterp + '\n<BR>\n'
333
334 if self._strExcList != None:
335 for item in self._strExcList:
336 excStr = excStr + str(item) + '\n<BR>'
337
338 return excStr
339
340 if __name__ == '__main__':
341
342 test = SchainNotify()
343
344 test.sendAlert('This is a message from the python module SchainNotify', 'Test from SchainNotify')
345
346 print 'Hopefully message sent - check.'
@@ -0,0 +1,5
1 #Copy this file to /etc/schain.conf
2 [schain]
3 CONTACT = miguel.urco@jro.igp.gob.pe
4 MAILSERVER = jro-zimbra.igp.gob.pe
5 MALSERVER_ACCOUNT = notifier-schain@jro.igp.gob.pe No newline at end of file
@@ -23,4 +23,7 VERSIONS:
23 -controller_api.py: Safe access to ControllerThead
23 -controller_api.py: Safe access to ControllerThead
24
24
25 2.1.3.3:
25 2.1.3.3:
26 -Colored Button Icons were added to GUI No newline at end of file
26 -Colored Button Icons were added to GUI
27
28 2.1.4:
29 -Sending error notifications to signal chain administrator No newline at end of file
@@ -4,4 +4,4 Created on Feb 7, 2012
4 @author $Author$
4 @author $Author$
5 @version $Id$
5 @version $Id$
6 '''
6 '''
7 __version__ = "2.1.3.3" No newline at end of file
7 __version__ = "2.1.4" No newline at end of file
@@ -2,18 +2,18
2 Created on September , 2012
2 Created on September , 2012
3 @author:
3 @author:
4 '''
4 '''
5 from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
6 from xml.dom import minidom
7
8 from model import *
9 from time import sleep
10
5
11 import sys
6 import sys
12 import ast
7 import ast
13 import traceback
8 import traceback
9 import schainpy
10 import schainpy.admin
14
11
15 SCHAIN_MAIL = "miguel.urco@jro.igp.gob.pe"
12 from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
16 EMAIL_SERVER = "jro.igp.gob.pe"
13 from xml.dom import minidom
14
15 from schainpy.model import *
16 from time import sleep
17
17
18 def prettify(elem):
18 def prettify(elem):
19 """Return a pretty-printed XML string for the Element.
19 """Return a pretty-printed XML string for the Element.
@@ -325,9 +325,9 class OperationConf():
325
325
326 return parmConfObj
326 return parmConfObj
327
327
328 def makeXml(self, upElement):
328 def makeXml(self, procUnitElement):
329
329
330 opElement = SubElement(upElement, self.ELEMENTNAME)
330 opElement = SubElement(procUnitElement, self.ELEMENTNAME)
331 opElement.set('id', str(self.id))
331 opElement.set('id', str(self.id))
332 opElement.set('name', self.name)
332 opElement.set('name', self.name)
333 opElement.set('type', self.type)
333 opElement.set('type', self.type)
@@ -539,16 +539,16 class ProcUnitConf():
539
539
540 return opConfObj
540 return opConfObj
541
541
542 def makeXml(self, procUnitElement):
542 def makeXml(self, projectElement):
543
543
544 upElement = SubElement(procUnitElement, self.ELEMENTNAME)
544 procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
545 upElement.set('id', str(self.id))
545 procUnitElement.set('id', str(self.id))
546 upElement.set('name', self.name)
546 procUnitElement.set('name', self.name)
547 upElement.set('datatype', self.datatype)
547 procUnitElement.set('datatype', self.datatype)
548 upElement.set('inputId', str(self.inputId))
548 procUnitElement.set('inputId', str(self.inputId))
549
549
550 for opConfObj in self.opConfObjList:
550 for opConfObj in self.opConfObjList:
551 opConfObj.makeXml(upElement)
551 opConfObj.makeXml(procUnitElement)
552
552
553 def readXml(self, upElement):
553 def readXml(self, upElement):
554
554
@@ -757,12 +757,53 class ReadUnitConf(ProcUnitConf):
757
757
758 return opObj
758 return opObj
759
759
760 # def makeXml(self, projectElement):
761 #
762 # procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
763 # procUnitElement.set('id', str(self.id))
764 # procUnitElement.set('name', self.name)
765 # procUnitElement.set('datatype', self.datatype)
766 # procUnitElement.set('inputId', str(self.inputId))
767 #
768 # for opConfObj in self.opConfObjList:
769 # opConfObj.makeXml(procUnitElement)
770
771 def readXml(self, upElement):
772
773 self.id = upElement.get('id')
774 self.name = upElement.get('name')
775 self.datatype = upElement.get('datatype')
776 self.inputId = upElement.get('inputId')
777
778 if self.ELEMENTNAME == "ReadUnit":
779 self.datatype = self.datatype.replace("Reader", "")
780
781 if self.inputId == 'None':
782 self.inputId = '0'
783
784 self.opConfObjList = []
785
786 opElementList = upElement.getiterator(OperationConf().getElementName())
787
788 for opElement in opElementList:
789 opConfObj = OperationConf()
790 opConfObj.readXml(opElement)
791 self.opConfObjList.append(opConfObj)
792
793 if opConfObj.name == 'run':
794 self.path = opConfObj.getParameterValue('path')
795 self.startDate = opConfObj.getParameterValue('startDate')
796 self.endDate = opConfObj.getParameterValue('endDate')
797 self.startTime = opConfObj.getParameterValue('startTime')
798 self.endTime = opConfObj.getParameterValue('endTime')
799
760 class Project():
800 class Project():
761
801
762 id = None
802 id = None
763 name = None
803 name = None
764 description = None
804 description = None
765 # readUnitConfObjList = None
805 filename = None
806
766 procUnitConfObjDict = None
807 procUnitConfObjDict = None
767
808
768 ELEMENTNAME = 'Project'
809 ELEMENTNAME = 'Project'
@@ -898,14 +939,26 class Project():
898
939
899 def writeXml(self, filename):
940 def writeXml(self, filename):
900
941
901 self.makeXml()
942 if not os.access(os.path.dirname(filename), os.W_OK):
943 return 0
902
944
903 #print prettify(self.projectElement)
945 if os.path.isfile(filename) and not(os.access(filename, os.W_OK)):
946 return 0
947
948 self.makeXml()
904
949
905 ElementTree(self.projectElement).write(filename, method='xml')
950 ElementTree(self.projectElement).write(filename, method='xml')
951
952 self.filename = filename
953
954 return 1
906
955
907 def readXml(self, filename):
956 def readXml(self, filename):
908
957
958 if not os.path.isfile(filename):
959 print "%s does not exist" %filename
960 return 0
961
909 self.projectElement = None
962 self.projectElement = None
910 self.procUnitConfObjDict = {}
963 self.procUnitConfObjDict = {}
911
964
@@ -938,7 +991,9 class Project():
938 procUnitConfObj.parentId = self.id
991 procUnitConfObj.parentId = self.id
939
992
940 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
993 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
941
994
995 return 1
996
942 def printattr(self):
997 def printattr(self):
943
998
944 print "Project[%s]: name = %s, description = %s" %(self.id,
999 print "Project[%s]: name = %s, description = %s" %(self.id,
@@ -1010,7 +1065,7 class Project():
1010
1065
1011 print
1066 print
1012 print "*"*60
1067 print "*"*60
1013 print " Starting SIGNAL CHAIN PROCESSING "
1068 print " Starting SIGNAL CHAIN PROCESSING v%s " %schainpy.__version__
1014 print "*"*60
1069 print "*"*60
1015 print
1070 print
1016
1071
@@ -1026,28 +1081,46 class Project():
1026
1081
1027 procUnitConfObj = self.procUnitConfObjDict[procKey]
1082 procUnitConfObj = self.procUnitConfObjDict[procKey]
1028
1083
1029 message = ""
1030 try:
1084 try:
1031 sts = procUnitConfObj.run()
1085 sts = procUnitConfObj.run()
1032 is_ok = is_ok or sts
1086 is_ok = is_ok or sts
1033 except:
1087 except:
1034 print "***** Error running %s *****" %procUnitConfObj.name
1088 print "***** Error occurred in %s *****" %(procUnitConfObj.name)
1035 sleep(1)
1089
1090 sleep(0.5)
1036
1091
1037 err = traceback.format_exception(sys.exc_info()[0],
1092 err = traceback.format_exception(sys.exc_info()[0],
1038 sys.exc_info()[1],
1093 sys.exc_info()[1],
1039 sys.exc_info()[2])
1094 sys.exc_info()[2])
1040
1095
1041 for thisLine in err:
1096 import socket
1042 message += thisLine
1097
1098 subject = "SChain v%s: Error running %s\n" %(schainpy.__version__, procUnitConfObj.name)
1099
1100 subtitle = "%s: %s\n" %(procUnitConfObj.getElementName() ,procUnitConfObj.name)
1101 subtitle += "Hostname: %s\n" %socket.gethostbyname(socket.gethostname())
1102 subtitle += "Working directory: %s\n" %os.path.abspath("./")
1103 subtitle += "Configuration file: %s\n" %self.filename
1104
1105 readUnitConfObj = self.getReadUnitObj()
1106 if readUnitConfObj:
1107 subtitle += "Data path: %s\n" %readUnitConfObj.path
1108 subtitle += "Data type: %s\n" %readUnitConfObj.datatype
1109 subtitle += "Start date: %s\n" %readUnitConfObj.startDate
1110 subtitle += "End date: %s\n" %readUnitConfObj.endDate
1111 subtitle += "Start time: %s\n" %readUnitConfObj.startTime
1112 subtitle += "End time: %s\n" %readUnitConfObj.endTime
1113
1114 message = "".join(err)
1043
1115
1044 sys.stderr.write(message)
1116 sys.stderr.write(message)
1045 # print "*"*60
1117
1046 # print message
1118 adminObj = schainpy.admin.SchainNotify()
1047 # print "*"*60
1119 adminObj.sendAlert(message=message,
1120 subject=subject,
1121 subtitle=subtitle,
1122 filename=self.filename)
1048
1123
1049 # self.sendReport(message)
1050 sleep(0.1)
1051 is_ok = False
1124 is_ok = False
1052
1125
1053 break
1126 break
@@ -1075,23 +1148,6 class Project():
1075 self.createObjects()
1148 self.createObjects()
1076 self.connectObjects()
1149 self.connectObjects()
1077 self.run()
1150 self.run()
1078
1079 def sendReport(self, message, subject="Error occurred in Signal Chain", email=SCHAIN_MAIL):
1080
1081 import smtplib
1082
1083 print subject
1084 print "Sending report to %s ..." %email
1085
1086 message = 'From: (Python Signal Chain API) ' + email + '\n' + \
1087 'To: ' + email + '\n' + \
1088 'Subject: ' + str(subject) + '\n' + \
1089 'Content-type: text/html\n\n' + message
1090
1091 server = smtplib.SMTP(EMAIL_SERVER)
1092 server.sendmail(email.split(',')[0],
1093 email.split(','), message)
1094 server.quit()
1095
1151
1096 if __name__ == '__main__':
1152 if __name__ == '__main__':
1097
1153
@@ -1,8 +1,5
1 import threading
1 import threading
2
2
3 from PyQt4 import QtCore
4 from PyQt4.QtCore import SIGNAL
5
6 from schainpy.controller import Project
3 from schainpy.controller import Project
7
4
8 class ControllerThread(threading.Thread, Project):
5 class ControllerThread(threading.Thread, Project):
@@ -74,68 +71,71 class ControllerThread(threading.Thread, Project):
74 def isFinished(self):
71 def isFinished(self):
75
72
76 return not self.is_alive()
73 return not self.is_alive()
77
74
78 class ControllerQThread(QtCore.QThread, Project):
75 # from PyQt4 import QtCore
79
76 # from PyQt4.QtCore import SIGNAL
80 def __init__(self, filename):
77 #
81
78 # class ControllerQThread(QtCore.QThread, Project):
82 QtCore.QThread.__init__(self)
79 #
83 Project.__init__(self)
80 # def __init__(self, filename):
84
81 #
85 self.filename = filename
82 # QtCore.QThread.__init__(self)
86
83 # Project.__init__(self)
87 self.lock = threading.Lock()
84 #
88 self.control = {'stop':False, 'pause':False}
85 # self.filename = filename
89
86 #
90 def __del__(self):
87 # self.lock = threading.Lock()
91
88 # self.control = {'stop':False, 'pause':False}
92 self.control['stop'] = True
89 #
93 self.wait()
90 # def __del__(self):
94
91 #
95 def stop(self):
92 # self.control['stop'] = True
96
93 # self.wait()
97 self.lock.acquire()
94 #
98
95 # def stop(self):
99 self.control['stop'] = True
96 #
100
97 # self.lock.acquire()
101 self.lock.release()
98 #
102
99 # self.control['stop'] = True
103 def pause(self):
100 #
104
101 # self.lock.release()
105 self.lock.acquire()
102 #
106
103 # def pause(self):
107 self.control['pause'] = not(self.control['pause'])
104 #
108 paused = self.control['pause']
105 # self.lock.acquire()
109
106 #
110 self.lock.release()
107 # self.control['pause'] = not(self.control['pause'])
111
108 # paused = self.control['pause']
112 return paused
109 #
113
110 # self.lock.release()
114 def isPaused(self):
111 #
115
112 # return paused
116 self.lock.acquire()
113 #
117 paused = self.control['pause']
114 # def isPaused(self):
118 self.lock.release()
115 #
119
116 # self.lock.acquire()
120 return paused
117 # paused = self.control['pause']
121
118 # self.lock.release()
122 def isStopped(self):
119 #
123
120 # return paused
124 self.lock.acquire()
121 #
125 stopped = self.control['stop']
122 # def isStopped(self):
126 self.lock.release()
123 #
127
124 # self.lock.acquire()
128 return stopped
125 # stopped = self.control['stop']
129
126 # self.lock.release()
130 def run(self):
127 #
131
128 # return stopped
132 self.control['stop'] = False
129 #
133 self.control['pause'] = False
130 # def run(self):
134
131 #
135 self.readXml(self.filename)
132 # self.control['stop'] = False
136 self.createObjects()
133 # self.control['pause'] = False
137 self.connectObjects()
134 #
138 self.emit( SIGNAL( "jobStarted( PyQt_PyObject )" ), 1)
135 # self.readXml(self.filename)
139 Project.run(self)
136 # self.createObjects()
140 self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), 1)
137 # self.connectObjects()
141 No newline at end of file
138 # self.emit( SIGNAL( "jobStarted( PyQt_PyObject )" ), 1)
139 # Project.run(self)
140 # self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), 1)
141 # No newline at end of file
@@ -27,7 +27,9 setup(name="schainpy",
27 'schainpy.gui.viewer.windows'},
27 'schainpy.gui.viewer.windows'},
28 py_modules=['schainpy.serializer.DataTranslate',
28 py_modules=['schainpy.serializer.DataTranslate',
29 'schainpy.serializer.JROSerializer'],
29 'schainpy.serializer.JROSerializer'],
30 package_data={'schainpy.gui.figures': ['*.png','*.jpg']},
30 package_data={'schainpy': ['*.cfg'],
31 'schainpy.gui.figures': ['*.png','*.jpg']
32 },
31 include_package_data=True,
33 include_package_data=True,
32 scripts =['schainpy/gui/schainGUI'],
34 scripts =['schainpy/gui/schainGUI'],
33 install_requires=["numpy >= 1.6.0",
35 install_requires=["numpy >= 1.6.0",
General Comments 0
You need to be logged in to leave comments. Login now