a2p2 0.7.4__tar.gz → 0.7.5__tar.gz
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-0.7.4/a2p2.egg-info → a2p2-0.7.5}/PKG-INFO +4 -2
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/jmmc/catalogs.py +92 -8
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/version.py +6 -2
- {a2p2-0.7.4 → a2p2-0.7.5/a2p2.egg-info}/PKG-INFO +4 -2
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2.egg-info/requires.txt +1 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/pyproject.toml +1 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/LICENSE +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/MANIFEST.in +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/README.rst +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/__init__.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/__main__.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/chara/__init__.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/chara/facility.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/chara/gui.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/client.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/facility.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/gui.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/instrument.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/jmmc/__init__.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/jmmc/generated_models.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/jmmc/models.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/jmmc/services.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/jmmc/utils.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/jmmc/webservices.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/ob.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/samp.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/utils.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/__init__.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/conf/GRAVITY_ditTable.json +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/conf/GRAVITY_rangeTable.json +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/conf/MATISSE_ditTable.json +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/conf/MATISSE_rangeTable.json +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/conf/PIONIER_ditTable.json +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/conf/PIONIER_rangeTable.json +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/facility.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/gravity.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/gui.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/instrument.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/matisse.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2/vlti/pionier.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2.egg-info/SOURCES.txt +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2.egg-info/dependency_links.txt +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2.egg-info/entry_points.txt +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/a2p2.egg-info/top_level.txt +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/setup.cfg +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/setup.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/test/test_jmmc_catalog.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/test/test_jmmc_models.py +0 -0
- {a2p2-0.7.4 → a2p2-0.7.5}/test/test_test.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: a2p2
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.5
|
4
4
|
Author-email: JMMC Tech Group <jmmc-tech-group@jmmc.fr>
|
5
5
|
License: OSI Approved :: GNU General Public License v3 (GPLv3)
|
6
6
|
Project-URL: Homepage, https://www.jmmc.fr/a2p2
|
@@ -16,7 +16,9 @@ Description-Content-Type: text/x-rst
|
|
16
16
|
License-File: LICENSE
|
17
17
|
Requires-Dist: appdirs
|
18
18
|
Requires-Dist: astropy>=5.2.2
|
19
|
+
Requires-Dist: pyvo>=1.6.1
|
19
20
|
Requires-Dist: p2api
|
21
|
+
Dynamic: license-file
|
20
22
|
|
21
23
|
a2p2 |A2P2Badge|
|
22
24
|
================
|
@@ -4,6 +4,9 @@ __all__ = []
|
|
4
4
|
|
5
5
|
import logging
|
6
6
|
|
7
|
+
import pyvo
|
8
|
+
import astropy.table.table
|
9
|
+
|
7
10
|
from ..client import A2P2ClientPreferences
|
8
11
|
|
9
12
|
from .utils import JmmcAPI
|
@@ -17,20 +20,36 @@ class Catalog():
|
|
17
20
|
Credential can be explicitly given for method that require an authentication, else:
|
18
21
|
- a2p2 preferences login will be used if present (see a2p2 -c)
|
19
22
|
- or uses .netrc file
|
23
|
+
A where clause can be added to limit on rows of interest (adql syntax)
|
24
|
+
A joins list of dictionnary can be provided to combine this catalog to other ones ( format is: [{"name":"cattojoin","id":"commonkey"},...] )
|
20
25
|
"""
|
21
26
|
|
22
|
-
def __init__(self, catalogName, username=None, password=None, prod=False, apiUrl=None):
|
27
|
+
def __init__(self, catalogName, username=None, password=None, prod=False, apiUrl=None, tapUrl=None, where=None, joins=None):
|
23
28
|
self.catalogName = catalogName
|
29
|
+
self.where = where
|
30
|
+
self.joins = joins
|
24
31
|
self.prod = prod
|
32
|
+
self.colDelimiterName = "coldelimiter___"
|
25
33
|
|
26
34
|
# Manage prod & preprod or user provided access points
|
27
35
|
if apiUrl:
|
28
36
|
self.apiUrl = apiUrl # trust given url as catalogAPI if value is provided
|
29
|
-
|
30
|
-
self.
|
31
|
-
|
32
|
-
|
33
|
-
|
37
|
+
if tapUrl:
|
38
|
+
self.tapUrl = tapUrl # trust given url as TAP server if value is provided
|
39
|
+
|
40
|
+
if not(apiUrl):
|
41
|
+
if self.prod:
|
42
|
+
self.apiUrl = "https://oidb.jmmc.fr/restxq/catalogs"
|
43
|
+
else:
|
44
|
+
self.apiUrl = "https://oidb-beta.jmmc.fr/restxq/catalogs"
|
45
|
+
|
46
|
+
if not(tapUrl):
|
47
|
+
if self.prod:
|
48
|
+
self.tapUrl = "https://tap.jmmc.fr/vollt/tap"
|
49
|
+
else:
|
50
|
+
self.tapUrl = "https://tap-preprod.jmmc.fr/vollt/tap"
|
51
|
+
|
52
|
+
self.tap = pyvo.dal.TAPService(self.tapUrl)
|
34
53
|
self.api = JmmcAPI(self.apiUrl, username, password)
|
35
54
|
|
36
55
|
logger.info(f"Create catalog wrapper to access '{catalogName}' ({PRODLABEL[self.prod]} API at {self.api.rootURL})")
|
@@ -40,7 +59,7 @@ class Catalog():
|
|
40
59
|
return self.api._get("")
|
41
60
|
|
42
61
|
def metadata(self):
|
43
|
-
""" Get catalog metadata
|
62
|
+
""" Get catalog metadata"""
|
44
63
|
return self.api._get(f"/meta/{self.catalogName}")
|
45
64
|
|
46
65
|
def pis(self):
|
@@ -66,12 +85,75 @@ class Catalog():
|
|
66
85
|
return pi["name"]
|
67
86
|
|
68
87
|
def getRow(self, id):
|
69
|
-
""" Get a single catalog record for the given id.
|
88
|
+
""" Get a single catalog record for the given id on the main catalog.
|
70
89
|
|
71
90
|
usage: cat.getRow(42)
|
72
91
|
"""
|
73
92
|
return self.api._get(f"/{self.catalogName}/{id}")
|
74
93
|
|
94
|
+
def getTable(self, maxrec=10000):
|
95
|
+
""" Get an astropy table from the main catalog joined the other if provided in constructor.
|
96
|
+
|
97
|
+
usage: cat.getRows()
|
98
|
+
"""
|
99
|
+
# using SELECT TOP N below to workarround astroquery.utils.tap BUG
|
100
|
+
|
101
|
+
clauses = []
|
102
|
+
if self.joins :
|
103
|
+
joinedCatalogNames = []
|
104
|
+
for join in self.joins:
|
105
|
+
joinedCatalogNames.append(join["name"] + ".*")
|
106
|
+
|
107
|
+
# colDelimiterName is added so we can keep the mainCatalog colnames for later updates (using rowsToDict)
|
108
|
+
clauses.append(f"SELECT TOP {maxrec} {self.catalogName}.*, '' as {self.colDelimiterName}, {', '.join(joinedCatalogNames)} FROM {self.catalogName}" )
|
109
|
+
|
110
|
+
for join in self.joins:
|
111
|
+
if "catalogKey" in join.keys():
|
112
|
+
catalogKey=join["catalogKey"]
|
113
|
+
else:
|
114
|
+
# we could use the (cached) metadata key, but this would add a additional remote call.A2P2ClientPreferences
|
115
|
+
# let's try with this convention using the same key name
|
116
|
+
catalogKey=join["id"]
|
117
|
+
name=join["name"]
|
118
|
+
id=join["id"]
|
119
|
+
# LEFT JOIN may be an option provided by join key ?
|
120
|
+
clauses.append (f" LEFT JOIN {name} ON {self.catalogName}.{catalogKey} = {name}.{id}")
|
121
|
+
|
122
|
+
if self.where:
|
123
|
+
clauses.append(f" WHERE {self.catalogName}.{self.where}")
|
124
|
+
else:
|
125
|
+
clauses.append(f"SELECT TOP {maxrec} * FROM {self.catalogName}")
|
126
|
+
if self.where:
|
127
|
+
clauses.append(f" WHERE {self.where}")
|
128
|
+
|
129
|
+
query = " ".join(clauses)
|
130
|
+
logger.info(f"Queriing TAP : {query}")
|
131
|
+
return self.tap.search(query,maxrec=maxrec).to_table()
|
132
|
+
|
133
|
+
|
134
|
+
def tableToDict(self, table):
|
135
|
+
""" Convert table (astropy.table or row) to a list of dict so we can modify content and update remote catalog using updateRows().
|
136
|
+
|
137
|
+
usage: cat.tableToDict(table)
|
138
|
+
"""
|
139
|
+
colnames = table.colnames
|
140
|
+
if "coldelimiter___" in colnames:
|
141
|
+
colnames = colnames[0:colnames.index("coldelimiter___")]
|
142
|
+
dicts=[]
|
143
|
+
# handle single row case
|
144
|
+
table = table if isinstance(table, astropy.table.table.Table ) else [table]
|
145
|
+
for row in table:
|
146
|
+
dict = {}
|
147
|
+
for colname in colnames:
|
148
|
+
v=row[colname]
|
149
|
+
if isinstance(v,str):
|
150
|
+
dict[colname] = v
|
151
|
+
else:
|
152
|
+
# avoid np.numeric type to make it json serializable
|
153
|
+
dict[colname] = v.item()
|
154
|
+
dicts.append(dict)
|
155
|
+
return dicts
|
156
|
+
|
75
157
|
def updateRow(self, id, values):
|
76
158
|
""" Update record identified by given id and associated values.
|
77
159
|
|
@@ -87,6 +169,7 @@ class Catalog():
|
|
87
169
|
"""
|
88
170
|
|
89
171
|
# We may check befere sending payload that we always provide an id for every record
|
172
|
+
# What is the behaviour if we provide various data assosiated to the same id ?
|
90
173
|
return self.api._put(f"/{self.catalogName}", values)
|
91
174
|
|
92
175
|
def addRows(self, values):
|
@@ -97,6 +180,7 @@ class Catalog():
|
|
97
180
|
"""
|
98
181
|
return self.api._post(f"/{self.catalogName}", json=values)
|
99
182
|
|
183
|
+
|
100
184
|
def getDelegations(self, pi=None):
|
101
185
|
""" Get -all- delegations.
|
102
186
|
A specific pi parameter may be given but requires admin priviledges. Else use current piname will be used by remote service.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
__version__ = "0.7.
|
1
|
+
__version__ = "0.7.5"
|
2
2
|
|
3
3
|
__release_notes__ = {
|
4
4
|
# "0.1.6": {
|
@@ -23,7 +23,11 @@ __release_notes__ = {
|
|
23
23
|
# "Try to read OB in P2 and send them back to Aspro2 as a new obs",
|
24
24
|
# ],
|
25
25
|
|
26
|
-
"0.7.
|
26
|
+
"0.7.5": {
|
27
|
+
"A2P2": [
|
28
|
+
"Add support for join and filter in a2p2.jmmc.Catalog wrapper",
|
29
|
+
],
|
30
|
+
},"0.7.4": {
|
27
31
|
"A2P2": [
|
28
32
|
"Use pyproject.toml for python installation",
|
29
33
|
],"VLTI": [
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: a2p2
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.5
|
4
4
|
Author-email: JMMC Tech Group <jmmc-tech-group@jmmc.fr>
|
5
5
|
License: OSI Approved :: GNU General Public License v3 (GPLv3)
|
6
6
|
Project-URL: Homepage, https://www.jmmc.fr/a2p2
|
@@ -16,7 +16,9 @@ Description-Content-Type: text/x-rst
|
|
16
16
|
License-File: LICENSE
|
17
17
|
Requires-Dist: appdirs
|
18
18
|
Requires-Dist: astropy>=5.2.2
|
19
|
+
Requires-Dist: pyvo>=1.6.1
|
19
20
|
Requires-Dist: p2api
|
21
|
+
Dynamic: license-file
|
20
22
|
|
21
23
|
a2p2 |A2P2Badge|
|
22
24
|
================
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|