a2p2 0.2.15__py3-none-any.whl → 0.7.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- a2p2/__main__.py +39 -0
- a2p2/chara/facility.py +51 -3
- a2p2/chara/gui.py +29 -5
- a2p2/client.py +144 -34
- a2p2/facility.py +11 -1
- a2p2/gui.py +32 -1
- a2p2/jmmc/__init__.py +7 -0
- a2p2/jmmc/catalogs.py +129 -0
- a2p2/jmmc/generated_models.py +191 -0
- a2p2/jmmc/models.py +104 -0
- a2p2/jmmc/services.py +16 -0
- a2p2/jmmc/utils.py +130 -0
- a2p2/jmmc/webservices.py +48 -0
- a2p2/ob.py +95 -9
- a2p2/samp.py +17 -0
- a2p2/version.py +205 -137
- a2p2/vlti/conf/GRAVITY_ditTable.json +21 -19
- a2p2/vlti/conf/GRAVITY_rangeTable.json +200 -28
- a2p2/vlti/conf/MATISSE_rangeTable.json +58 -22
- a2p2/vlti/conf/PIONIER_ditTable.json +1 -1
- a2p2/vlti/conf/PIONIER_rangeTable.json +16 -18
- a2p2/vlti/facility.py +156 -118
- a2p2/vlti/gravity.py +243 -311
- a2p2/vlti/gui.py +162 -40
- a2p2/vlti/instrument.py +264 -49
- a2p2/vlti/matisse.py +61 -147
- a2p2/vlti/pionier.py +34 -157
- {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/METADATA +34 -20
- a2p2-0.7.4.dist-info/RECORD +39 -0
- {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/WHEEL +1 -1
- {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/entry_points.txt +0 -1
- a2p2/vlti/confP104/GRAVITY_ditTable.json +0 -122
- a2p2/vlti/confP104/GRAVITY_rangeTable.json +0 -202
- a2p2/vlti/confP104/MATISSE_ditTable.json +0 -2
- a2p2/vlti/confP104/MATISSE_rangeTable.json +0 -202
- a2p2/vlti/confP104/PIONIER_ditTable.json +0 -77
- a2p2/vlti/confP104/PIONIER_rangeTable.json +0 -118
- a2p2/vlti/confP105/GRAVITY_ditTable.json +0 -37
- a2p2/vlti/confP105/GRAVITY_rangeTable.json +0 -42
- a2p2/vlti/confP105/MATISSE_ditTable.json +0 -2
- a2p2/vlti/confP105/MATISSE_rangeTable.json +0 -44
- a2p2/vlti/confP105/PIONIER_ditTable.json +0 -25
- a2p2/vlti/confP105/PIONIER_rangeTable.json +0 -38
- a2p2-0.2.15.dist-info/RECORD +0 -44
- {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/LICENSE +0 -0
- {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/top_level.txt +0 -0
a2p2/__main__.py
CHANGED
@@ -2,7 +2,40 @@
|
|
2
2
|
from __future__ import with_statement
|
3
3
|
|
4
4
|
import traceback
|
5
|
+
|
5
6
|
from argparse import ArgumentParser
|
7
|
+
from a2p2 import __release_notes__
|
8
|
+
from distutils.version import LooseVersion
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
def createMdReleaseNotes():
|
13
|
+
"""
|
14
|
+
Present in a reverse ordered way the dictionnary version items.
|
15
|
+
"""
|
16
|
+
txt = "# A2P2 release notes"
|
17
|
+
lvs = [LooseVersion(v) for v in __release_notes__]
|
18
|
+
for lv in sorted(lvs, reverse=True):
|
19
|
+
v=lv.vstring
|
20
|
+
txt += "\n## V " + v + " :"
|
21
|
+
keys = []
|
22
|
+
for k in sorted(__release_notes__[v]):
|
23
|
+
if not ("TODO" in k):
|
24
|
+
keys.append(k)
|
25
|
+
for k in sorted(__release_notes__[v]):
|
26
|
+
if "TODO" in k:
|
27
|
+
keys.append(k)
|
28
|
+
|
29
|
+
for e in keys:
|
30
|
+
infos = __release_notes__[v][e]
|
31
|
+
if infos:
|
32
|
+
txt += "\n### " + e + " : "
|
33
|
+
for i in infos:
|
34
|
+
txt += "\n- " + i
|
35
|
+
txt += "\n\n"
|
36
|
+
f=open("release-notes.md", "w")
|
37
|
+
f.write(txt)
|
38
|
+
print(f"{f.name} generated")
|
6
39
|
|
7
40
|
|
8
41
|
def main():
|
@@ -14,15 +47,21 @@ def main():
|
|
14
47
|
help='fake API to avoid remote connection (dev. only).')
|
15
48
|
parser.add_argument('-v', '--verbose', action='store_true', help='Verbose')
|
16
49
|
parser.add_argument('-c', '--createprefs', action='store_true', help='Create preferences file')
|
50
|
+
parser.add_argument('-r', '--releasenotes', action='store_true', help='Create md release notes file')
|
17
51
|
|
18
52
|
args = parser.parse_args()
|
19
53
|
|
20
54
|
from . import A2p2Client
|
21
55
|
|
56
|
+
if args.releasenotes:
|
57
|
+
createMdReleaseNotes()
|
58
|
+
exit()
|
59
|
+
|
22
60
|
if args.createprefs:
|
23
61
|
A2p2Client.createPreferencesFile()
|
24
62
|
exit()
|
25
63
|
|
64
|
+
|
26
65
|
try:
|
27
66
|
with A2p2Client(args.fakeapi, args.verbose) as a2p2c:
|
28
67
|
# if args.config:
|
a2p2/chara/facility.py
CHANGED
@@ -4,7 +4,9 @@ __all__ = []
|
|
4
4
|
|
5
5
|
from a2p2.chara.gui import CharaUI
|
6
6
|
from a2p2.facility import Facility
|
7
|
+
import requests
|
7
8
|
import logging
|
9
|
+
import traceback
|
8
10
|
|
9
11
|
HELPTEXT = "TODO update this HELP message in a2p2/chara/facility.py"
|
10
12
|
|
@@ -15,8 +17,13 @@ class CharaFacility(Facility):
|
|
15
17
|
def __init__(self, a2p2client):
|
16
18
|
Facility.__init__(self, a2p2client, "CHARA", HELPTEXT)
|
17
19
|
self.charaUI = CharaUI(self)
|
20
|
+
self.connected2OB2 = False
|
21
|
+
self.validQueueServer = None
|
18
22
|
|
19
23
|
def processOB(self, ob):
|
24
|
+
if not ob:
|
25
|
+
return
|
26
|
+
|
20
27
|
self.a2p2client.ui.addToLog(
|
21
28
|
"OB received for '" + self.facilityName + "' interferometer")
|
22
29
|
# show ob dict for debug
|
@@ -28,8 +35,49 @@ class CharaFacility(Facility):
|
|
28
35
|
# give focus on last updated UI
|
29
36
|
self.a2p2client.ui.showFacilityUI(self.charaUI)
|
30
37
|
|
38
|
+
def checkServer(self):
|
39
|
+
if self.validQueueServer:
|
40
|
+
# recheck ?
|
41
|
+
return True
|
42
|
+
else:
|
43
|
+
# search and test servers from preferences
|
44
|
+
queueServers=self.a2p2client.preferences.getCharaQueueServer()
|
45
|
+
msg=""
|
46
|
+
if queueServers :
|
47
|
+
for queueServer in queueServers:
|
48
|
+
logger.debug(f'Trying to send OB on queuserver : {queueServer}')
|
49
|
+
try:
|
50
|
+
c=requests.get(queueServer, timeout=3)
|
51
|
+
msg+=f"Connection succeeded on OB server : {c.json()}\n"
|
52
|
+
self.validQueueServer = queueServer
|
53
|
+
break
|
54
|
+
except:
|
55
|
+
msg+=f"Connection failed on {queueServer}\n"
|
56
|
+
|
57
|
+
self.a2p2client.ui.addToLog(msg)
|
58
|
+
self.charaUI.display(msg)
|
59
|
+
|
60
|
+
return self.validQueueServer
|
61
|
+
|
31
62
|
def consumeOB(self, ob):
|
32
|
-
|
33
|
-
|
34
|
-
|
63
|
+
if self.checkServer():
|
64
|
+
try:
|
65
|
+
r = requests.post(self.validQueueServer, json=ob.as_dict(), timeout=3)
|
66
|
+
msg = ""
|
67
|
+
msg+=f"OB sent to remote server queue : {r}"
|
68
|
+
self.connected2OB2 = True
|
69
|
+
self.a2p2client.ui.addToLog(msg)
|
70
|
+
self.charaUI.display(msg)
|
71
|
+
except:
|
72
|
+
print(traceback.format_exc())
|
73
|
+
msg=f"Can't send OB to the '{self.validQueueServer}' queue server, please relaunch it or try again for a new one."
|
74
|
+
self.validQueueServer = None
|
75
|
+
self.a2p2client.ui.addToLog(msg)
|
76
|
+
self.charaUI.display(msg)
|
77
|
+
else:
|
78
|
+
msg=f"Can't find any queue server, please launch it, edit your preferences or check your ssh port forwarding"
|
79
|
+
|
80
|
+
# display OB
|
35
81
|
self.charaUI.displayOB(ob)
|
82
|
+
|
83
|
+
|
a2p2/chara/gui.py
CHANGED
@@ -42,6 +42,10 @@ class CharaUI(FacilityUI):
|
|
42
42
|
else:
|
43
43
|
return None
|
44
44
|
|
45
|
+
def display(self, msg):
|
46
|
+
self.text.insert(END, msg)
|
47
|
+
|
48
|
+
|
45
49
|
def displayOB(self, ob):
|
46
50
|
try:
|
47
51
|
buffer = self.extractReport(ob)
|
@@ -91,8 +95,8 @@ AO Flat Star:
|
|
91
95
|
targets = {} # store ids for futur retrieval in schedule
|
92
96
|
for oc in ob.observationConfiguration:
|
93
97
|
targets[oc.id] = oc
|
94
|
-
if "SCI" in oc.type:
|
95
|
-
|
98
|
+
# if "SCI" in oc.type:
|
99
|
+
sciences.append(oc)
|
96
100
|
|
97
101
|
# Retrieve cals from schedule
|
98
102
|
cals = {}
|
@@ -109,13 +113,28 @@ AO Flat Star:
|
|
109
113
|
|
110
114
|
for oc in sciences:
|
111
115
|
sct = oc.SCTarget
|
116
|
+
extrainfos = self.get(sct, "EXTRA_INFORMATIONS")
|
112
117
|
ftt = self.get(oc, "FTTarget")
|
113
118
|
aot = self.get(oc, "AOTarget")
|
114
|
-
|
115
|
-
|
119
|
+
|
120
|
+
if self.get(oc,'observationConstraints'):
|
121
|
+
buffer += ", ".join(oc.observationConstraints.LSTinterval) + "\n"
|
122
|
+
else:
|
123
|
+
buffer += " NOT OBSERVABLE \n"
|
124
|
+
buffer += f"{oc.type} Object:\n"
|
116
125
|
fluxes = ", ".join([e[0] + "=" + e[1]
|
117
126
|
for e in ob.getFluxes(sct).items()])
|
118
|
-
|
127
|
+
try:
|
128
|
+
info = sct.SPECTYP
|
129
|
+
except:
|
130
|
+
info = "no SPECTYP"
|
131
|
+
info+=", "
|
132
|
+
try:
|
133
|
+
info += sct.PARALLAX
|
134
|
+
except:
|
135
|
+
info += "no PARALLAX"
|
136
|
+
|
137
|
+
|
119
138
|
buffer += sct.name + " (" + info + ") : " + fluxes + "\n"
|
120
139
|
if ftt:
|
121
140
|
buffer += "Fringe Finder:\n"
|
@@ -133,6 +152,11 @@ AO Flat Star:
|
|
133
152
|
for cal in cals:
|
134
153
|
buffer += "- " + cal + "\n"
|
135
154
|
|
155
|
+
# Display Extra_Informations if any
|
156
|
+
if extrainfos:
|
157
|
+
buffer += "Extra_infos:\n"
|
158
|
+
buffer += ", ".join([f"{field}={self.get(extrainfos,field)}" for field in extrainfos._fields])
|
159
|
+
|
136
160
|
buffer += _HR
|
137
161
|
|
138
162
|
return buffer
|
a2p2/client.py
CHANGED
@@ -16,19 +16,23 @@ from a2p2.samp import A2p2SampClient
|
|
16
16
|
from a2p2.vlti.facility import VltiFacility
|
17
17
|
|
18
18
|
|
19
|
+
|
19
20
|
# prepare global logging
|
20
21
|
a2p2Rootlogger = logging.getLogger("a2p2")
|
21
|
-
# uncomment next line to log requests done by p2api and maybe other ones...
|
22
|
-
#a2p2Rootlogger = logging.getLogger()
|
23
22
|
a2p2Rootlogger.setLevel(logging.INFO)
|
23
|
+
# uncomment next two lines to log requests done by p2api as debug and maybe other ones...
|
24
|
+
#a2p2Rootlogger = logging.getLogger()
|
25
|
+
#a2p2Rootlogger.setLevel(logging.DEBUG)
|
24
26
|
console = logging.StreamHandler()
|
25
27
|
console.setLevel(logging.DEBUG)
|
26
|
-
consoleFormatter = logging.Formatter(
|
28
|
+
consoleFormatter = logging.Formatter(
|
29
|
+
'%(levelname)s - %(name)s - %(asctime)s - %(filename)s:%(lineno)d - %(message)s')
|
27
30
|
console.setFormatter(consoleFormatter)
|
28
31
|
a2p2Rootlogger.addHandler(console)
|
29
32
|
|
30
33
|
logger = logging.getLogger(__name__)
|
31
34
|
|
35
|
+
|
32
36
|
class A2p2Client():
|
33
37
|
"""Transmit your Aspro2 observation to remote Observatory scheduling database.
|
34
38
|
|
@@ -36,7 +40,6 @@ class A2p2Client():
|
|
36
40
|
a2p2.run()
|
37
41
|
..."""
|
38
42
|
|
39
|
-
|
40
43
|
def __init__(self, fakeAPI=False, verbose=False):
|
41
44
|
"""Create the A2p2 client."""
|
42
45
|
|
@@ -56,11 +59,17 @@ class A2p2Client():
|
|
56
59
|
self.facilityManager = FacilityManager(self)
|
57
60
|
|
58
61
|
if self.preferences.exists():
|
59
|
-
|
62
|
+
A2P2ClientPreferences.updatePreferencesFile()
|
63
|
+
self.ui.addToLog(
|
64
|
+
f"Using preference from '{A2P2ClientPreferences.getPreferencesFileName()}'.\n")
|
60
65
|
else:
|
61
|
-
self.ui.addToLog(
|
66
|
+
self.ui.addToLog(
|
67
|
+
"No preference file found, please create one so your data persists (launch program with -c option).\n")
|
62
68
|
|
63
|
-
self.
|
69
|
+
self.ui.addToLog("Please often update ( pip install -U [--user] a2p2 ) and don't hesitate to send any feedback or issues!\n\n")
|
70
|
+
|
71
|
+
|
72
|
+
self.errors = []
|
64
73
|
|
65
74
|
pass
|
66
75
|
|
@@ -120,16 +129,16 @@ class A2p2Client():
|
|
120
129
|
|
121
130
|
# handle autologin
|
122
131
|
if self.preferences.getP2AutoLoginBoolean():
|
123
|
-
logger.debug("Autologin using '%s' file"%
|
124
|
-
|
132
|
+
logger.debug("Autologin using '%s' file" %
|
133
|
+
A2P2ClientPreferences.getPreferencesFileName())
|
125
134
|
self.ui.loop()
|
126
|
-
vltifacility = self.facilityManager.facilities.get(
|
135
|
+
vltifacility = self.facilityManager.facilities.get(
|
136
|
+
VltiFacility.getName())
|
127
137
|
vltifacility.autologin()
|
128
138
|
|
129
|
-
|
130
139
|
# We now run the loop to wait for the message in a try/finally block so that if
|
131
140
|
# the program is interrupted e.g. by control-C, the client terminates
|
132
|
-
# gracefully.
|
141
|
+
# gracefully. ( but sometimes fails inside tkinter/__init__.py CallWrapper/__call__() )
|
133
142
|
|
134
143
|
# We test every 1s to see if the hub has sent a message
|
135
144
|
delay = 0.1
|
@@ -142,8 +151,14 @@ class A2p2Client():
|
|
142
151
|
loop_cnt += 1
|
143
152
|
time.sleep(delay)
|
144
153
|
|
154
|
+
# if loop_cnt % each == 0:
|
155
|
+
# logger.debug(f"loop {loop_cnt}")
|
156
|
+
|
145
157
|
self.ui.loop()
|
146
158
|
|
159
|
+
# process any stacked OBs
|
160
|
+
self.facilityManager.processOB()
|
161
|
+
|
147
162
|
if not self.a2p2SampClient.is_connected() and loop_cnt % each == 0:
|
148
163
|
try:
|
149
164
|
self.a2p2SampClient.connect()
|
@@ -159,11 +174,21 @@ class A2p2Client():
|
|
159
174
|
|
160
175
|
if self.a2p2SampClient.has_message():
|
161
176
|
try:
|
162
|
-
|
163
|
-
|
177
|
+
if self.a2p2SampClient.has_ob_message():
|
178
|
+
ob = OB(self.a2p2SampClient.get_ob_url())
|
179
|
+
self.facilityManager.processOB(ob)
|
164
180
|
except:
|
165
181
|
self.ui.addToLog(
|
166
|
-
"Exception during ob creation: " + traceback.format_exc(), False)
|
182
|
+
"Exception during a2p2 ob creation: " + traceback.format_exc(), False)
|
183
|
+
self.ui.addToLog("Can't process last OB")
|
184
|
+
|
185
|
+
try:
|
186
|
+
if self.a2p2SampClient.has_model_message():
|
187
|
+
m = self.a2p2SampClient.get_model()
|
188
|
+
self.showModel(m)
|
189
|
+
except:
|
190
|
+
self.ui.addToLog(
|
191
|
+
"Exception during a2p2 ob creation: " + traceback.format_exc(), False)
|
167
192
|
self.ui.addToLog("Can't process last OB")
|
168
193
|
|
169
194
|
# always clear previous received message
|
@@ -173,16 +198,27 @@ class A2p2Client():
|
|
173
198
|
loop_cnt = -1
|
174
199
|
except KeyboardInterrupt:
|
175
200
|
loop_cnt = -1
|
201
|
+
print("\nDisconnecting SAMP ...")
|
202
|
+
self.a2p2SampClient.disconnect()
|
203
|
+
print("Bye!")
|
204
|
+
|
176
205
|
|
177
206
|
def createPreferencesFile():
|
178
207
|
A2P2ClientPreferences.createPreferencesFile()
|
179
208
|
|
209
|
+
|
210
|
+
def showModel(self, xmlmodel):
|
211
|
+
from a2p2.jmmc.models import modelsFromXml
|
212
|
+
self.ui.addToLog("Received star model")
|
213
|
+
self.ui.addToLog(modelsFromXml(xmlmodel))
|
214
|
+
|
215
|
+
|
180
216
|
class A2P2ClientPreferences():
|
181
217
|
# define application name
|
182
218
|
appname = "a2p2"
|
183
219
|
|
184
220
|
def __init__(self):
|
185
|
-
self._config =
|
221
|
+
self._config = A2P2ClientPreferences.getPreferences()
|
186
222
|
pass
|
187
223
|
|
188
224
|
def exists(self):
|
@@ -193,36 +229,84 @@ class A2P2ClientPreferences():
|
|
193
229
|
|
194
230
|
def getPreferences():
|
195
231
|
preferences_file = A2P2ClientPreferences.getPreferencesFileName()
|
196
|
-
config = configparser.ConfigParser()
|
232
|
+
config = configparser.ConfigParser(allow_no_value=True)
|
197
233
|
config.read(preferences_file)
|
198
234
|
return config
|
199
235
|
|
200
236
|
def getPreferencesFileName():
|
201
237
|
from appdirs import user_config_dir
|
202
|
-
preferences_file = os.path.join(user_config_dir(
|
238
|
+
preferences_file = os.path.join(user_config_dir(
|
239
|
+
A2P2ClientPreferences.appname), "prefs.ini")
|
203
240
|
return preferences_file
|
241
|
+
def updatePreferencesFile():
|
242
|
+
return
|
243
|
+
# TODO
|
244
|
+
# we suppose the file exists
|
245
|
+
filename = A2P2ClientPreferences.getPreferencesFileName()
|
246
|
+
buffer=""
|
247
|
+
for line in open(filename):
|
248
|
+
buffer+=line+"\n"
|
249
|
+
print (buffer)
|
204
250
|
|
205
251
|
def createPreferencesFile():
|
206
|
-
filename=A2P2ClientPreferences.getPreferencesFileName()
|
207
|
-
|
252
|
+
filename = A2P2ClientPreferences.getPreferencesFileName()
|
208
253
|
if os.path.exists(filename):
|
209
|
-
print("
|
254
|
+
print(f"{filename} already exists. Nothing done")
|
255
|
+
p=A2P2ClientPreferences()
|
256
|
+
versionInPref=p.getA2P2Version()
|
257
|
+
if __version__ != versionInPref:
|
258
|
+
print(f"HINT: You may try to backup this file (V{versionInPref}) and merge with a new generated one for V{__version__}.")
|
210
259
|
else:
|
211
|
-
|
260
|
+
import getpass
|
261
|
+
|
262
|
+
config = configparser.ConfigParser(allow_no_value=True)
|
212
263
|
#config['DEFAULT'] = {'_noprefyet': '42'}
|
264
|
+
|
265
|
+
config['a2p2'] = {}
|
266
|
+
s = config['a2p2']
|
267
|
+
s['# A2P2 SECTION'] = ""
|
268
|
+
s['# = > please do not modify next properties <'] = ""
|
269
|
+
s['version'] = __version__
|
270
|
+
|
271
|
+
|
272
|
+
config['jmmc'] = {}
|
273
|
+
s = config['jmmc']
|
274
|
+
s['# JMMC SECTION'] = ""
|
275
|
+
s['# = > please uncomment and update next properties to make it active <'] = ""
|
276
|
+
s['#login'] = "my.email@my.lab"
|
277
|
+
s['#password'] = "12345zZ"
|
278
|
+
|
279
|
+
config['chara'] = {}
|
280
|
+
s = config['chara']
|
281
|
+
s['# CHARA SECTION'] = ""
|
282
|
+
s['# = > please uncomment and update next properties to make it active <'] = ""
|
283
|
+
s['# = > queueserver may be uncommented to forward OB to a remote server instead <'] = ""
|
284
|
+
s['#queueserver'] = 'http://192.168.3.153:2468/test,http://localhost:2468/test'
|
285
|
+
|
213
286
|
config['p2'] = {}
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
287
|
+
s=config['p2']
|
288
|
+
s['# ESO P2 SECTION'] = ""
|
289
|
+
s['# = > please uncomment and update next properties to make it active <'] = ""
|
290
|
+
s['#username'] = getpass.getuser()
|
291
|
+
s['#password'] = "12345zZ"
|
292
|
+
s['#autologin'] = "yes"
|
293
|
+
s['# = > please change next properties to change the name recorded in the OB comments <'] = ""
|
294
|
+
s['user_comment_name'] = f"{getpass.getuser()}"
|
295
|
+
|
296
|
+
config['p2.iss.vltitype'] = {}
|
297
|
+
s=config['p2.iss.vltitype']
|
298
|
+
s['# = > please uncomment the default values to add for ISS.VLTITYPE <'] = ""
|
299
|
+
s['# = > all supported will be added for any VLTI instrument if info is not provided by Aspro2 <'] = None
|
300
|
+
s['#snapshot'] = None
|
301
|
+
s['#imaging'] = None
|
302
|
+
s['#time-series'] = None
|
303
|
+
s['#astrometry'] = None
|
220
304
|
|
221
305
|
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
222
306
|
with open(filename, 'w+') as configfile:
|
223
307
|
config.write(configfile)
|
224
308
|
|
225
|
-
print("%s template created. Please adjust."%filename)
|
309
|
+
print("'%s' template file created to store preferences. Please check and adjust it's content." % filename)
|
226
310
|
|
227
311
|
def getConfig(self, section, key, default=None):
|
228
312
|
try:
|
@@ -230,19 +314,44 @@ class A2P2ClientPreferences():
|
|
230
314
|
except:
|
231
315
|
return default
|
232
316
|
|
317
|
+
def getConfigKeys(self, section, default=None):
|
318
|
+
try:
|
319
|
+
return list(self._config[section].keys())
|
320
|
+
except:
|
321
|
+
return default
|
322
|
+
|
323
|
+
|
233
324
|
def getConfigBoolean(self, section, key, default=None):
|
234
325
|
try:
|
235
|
-
return self._config.getboolean(section,key)
|
326
|
+
return self._config.getboolean(section, key)
|
236
327
|
except:
|
237
328
|
return default
|
238
329
|
|
330
|
+
# Retrieve A2P2 prefs
|
331
|
+
def getA2P2Version(self):
|
332
|
+
return self.getConfig("a2p2", "version", 'missing')
|
333
|
+
|
334
|
+
# Retrieve JMMC prefs
|
335
|
+
def getJmmcLogin(self):
|
336
|
+
return self.getConfig("jmmc", "login", None)
|
239
337
|
|
240
|
-
|
338
|
+
def getJmmcPassword(self):
|
339
|
+
return self.getConfig("jmmc", "password", None)
|
340
|
+
|
341
|
+
# Retrieve CHARA prefs
|
342
|
+
def getCharaQueueServer(self):
|
343
|
+
s = self.getConfig("chara", "queueserver", None)
|
344
|
+
if s:
|
345
|
+
return s.split(",")
|
346
|
+
|
347
|
+
|
348
|
+
# Retrieve P2 prefs
|
241
349
|
def getP2Username(self):
|
242
|
-
|
350
|
+
""" Get P2 username in config or use default demo account """
|
351
|
+
return self.getConfig("p2", "username", '52052')
|
243
352
|
|
244
|
-
# retrieve P2 password in config or use default demo account
|
245
353
|
def getP2Password(self):
|
354
|
+
"""Get P2 password in config or use default demo account"""
|
246
355
|
return self.getConfig("p2", "password", 'tutorial')
|
247
356
|
|
248
357
|
def getP2UserCommentName(self):
|
@@ -250,5 +359,6 @@ class A2P2ClientPreferences():
|
|
250
359
|
return self.getConfig("p2", "user_comment_name", getpass.getuser())
|
251
360
|
|
252
361
|
def getP2AutoLoginBoolean(self):
|
253
|
-
|
362
|
+
return self.getConfigBoolean("p2", "autologin", False)
|
363
|
+
|
254
364
|
|
a2p2/facility.py
CHANGED
@@ -38,7 +38,17 @@ class FacilityManager():
|
|
38
38
|
|
39
39
|
return " | ".join(status)
|
40
40
|
|
41
|
-
def processOB(self, ob):
|
41
|
+
def processOB(self, ob=None):
|
42
|
+
|
43
|
+
# handled queued obs if ob is null
|
44
|
+
# TODO add a new method in the futur
|
45
|
+
if not ob:
|
46
|
+
for f in self.facilities.values():
|
47
|
+
f.processOB(ob)
|
48
|
+
return
|
49
|
+
|
50
|
+
# else handle given ob
|
51
|
+
|
42
52
|
""" Test instrument on facility that registerInstrument() before OB forward for specialized handling."""
|
43
53
|
interferometer = ob.interferometerConfiguration.name
|
44
54
|
insname = ob.instrumentConfiguration.name
|
a2p2/gui.py
CHANGED
@@ -19,6 +19,8 @@ else:
|
|
19
19
|
|
20
20
|
from distutils.version import LooseVersion
|
21
21
|
|
22
|
+
import signal
|
23
|
+
|
22
24
|
HELPTEXT = """This application provides the link between ASPRO (that you should have started) and interferometers facilities.
|
23
25
|
|
24
26
|
"""
|
@@ -44,6 +46,8 @@ class MainWindow():
|
|
44
46
|
print("Can not set tk scaling !")
|
45
47
|
|
46
48
|
self.window.protocol("WM_DELETE_WINDOW", self._requestAbort)
|
49
|
+
# throws an exception self.window.bind_all('<Control-c>', self._requestAbort) # maybe already bound with WM_DELETE_WINDOW ?
|
50
|
+
signal.signal(signal.SIGINT, self._requestAbortSignal)
|
47
51
|
|
48
52
|
self.notebook = ttk.Notebook(self.window)
|
49
53
|
|
@@ -96,6 +100,10 @@ class MainWindow():
|
|
96
100
|
def _requestAbort(self):
|
97
101
|
self.requestAbort = True
|
98
102
|
|
103
|
+
def _requestAbortSignal(self, arg1,arg2):
|
104
|
+
self.requestAbort = True
|
105
|
+
|
106
|
+
|
99
107
|
def addHelp(self, tabname, txt):
|
100
108
|
frame = Frame(self.helptabs)
|
101
109
|
widget = Text(frame, width=120)
|
@@ -176,8 +184,12 @@ class MainWindow():
|
|
176
184
|
self.logtext.insert(END, "\n" + str(text))
|
177
185
|
self.logtext.see(END)
|
178
186
|
self.showFrameToFront()
|
187
|
+
self.refresh()
|
179
188
|
logger.log(level,text)
|
180
189
|
|
190
|
+
def refresh(self):
|
191
|
+
self.window.update()
|
192
|
+
|
181
193
|
def ShowErrorMessage(self, text):
|
182
194
|
if self.a2p2client.fakeAPI:
|
183
195
|
pass
|
@@ -195,7 +207,7 @@ class MainWindow():
|
|
195
207
|
else:
|
196
208
|
showwarning("Warning", text)
|
197
209
|
self.addToLog("Warning message")
|
198
|
-
self.addToLog(text, False,
|
210
|
+
self.addToLog(text, False, logging.WARNING)
|
199
211
|
|
200
212
|
def ShowInfoMessage(self, text):
|
201
213
|
if self.a2p2client.fakeAPI:
|
@@ -205,6 +217,19 @@ class MainWindow():
|
|
205
217
|
self.addToLog("Info message")
|
206
218
|
self.addToLog(text, False, logging.INFO)
|
207
219
|
|
220
|
+
def AskYesNoMessage(self, text):
|
221
|
+
if self.a2p2client.fakeAPI:
|
222
|
+
pass
|
223
|
+
else:
|
224
|
+
self.addToLog(f"Question: {text}", displayString=False)
|
225
|
+
ret = askyesno("", text)
|
226
|
+
self.addToLog(f"Reply: yes={ret}", displayString=False)
|
227
|
+
return ret
|
228
|
+
|
229
|
+
def addProgress(self, offset=0.1):
|
230
|
+
self.setProgress(self.progress_value.get()+offset)
|
231
|
+
|
232
|
+
|
208
233
|
def setProgress(self, perc):
|
209
234
|
if perc > 1:
|
210
235
|
perc = perc / 100.0
|
@@ -268,6 +293,12 @@ class FacilityUI(Frame):
|
|
268
293
|
def ShowInfoMessage(self, *args, **kwargs):
|
269
294
|
self.a2p2client.ui.ShowInfoMessage(*args, **kwargs)
|
270
295
|
|
296
|
+
def AskYesNoMessage(self,*args, **kwargs):
|
297
|
+
return self.a2p2client.ui.AskYesNoMessage(*args, **kwargs)
|
298
|
+
|
299
|
+
def addProgress(self, offset=0.1):
|
300
|
+
self.a2p2client.ui.addProgress(offset)
|
301
|
+
|
271
302
|
def setProgress(self, perc):
|
272
303
|
""" Wrapper to update progress bar """
|
273
304
|
if perc > 1:
|