Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
AndrewVSutherland
GitHub Repository: AndrewVSutherland/lmfdb
Path: blob/main/scripts/reports/inventory_legacy_uploader.py
1128 views
1
import json
2
import lmfdb.inventory_app.inventory_helpers as ih
3
import lmfdb.inventory_app.lmfdb_inventory as inv
4
import lmfdb.inventory_app.inventory_db_core as invc
5
from lmfdb.inventory_app.inventory_upload_data import (upload_collection_structure, extract_specials, delete_all_tables, recreate_rollback_table, MAX_SZ, delete_by_collection)
6
7
def upload_all_structure(db, structure_dat):
8
"""Upload an everything from a structure json document
9
10
db -- LMFDB connection to inventory database
11
structure_dat -- JSON document containing all db/collections to upload
12
"""
13
14
inv.log_dest.info("_____________________________________________________________________________________________")
15
inv.log_dest.info("Processing structure data")
16
n_dbs = len(structure_dat.keys())
17
progress_tracker = 0
18
19
for DB_name in structure_dat:
20
progress_tracker += 1
21
inv.log_dest.info("Uploading " + DB_name+" ("+str(progress_tracker)+" of "+str(n_dbs)+')')
22
invc.set_db(db, DB_name, DB_name)
23
24
for coll_name in structure_dat[DB_name]:
25
inv.log_dest.info(" Uploading collection "+coll_name)
26
orphaned_keys = upload_collection_structure(db, DB_name, coll_name, structure_dat, fresh=False)
27
if len(orphaned_keys) != 0:
28
with open('Orph_'+DB_name+'_'+coll_name+'.json', 'w') as file:
29
file.write(json.dumps(orphaned_keys))
30
inv.log_dest.info(" Orphans written to Orph_"+ DB_name+'_'+coll_name+'.json')
31
32
def upload_from_files(db, master_file_name, list_file_name, fresh=False):
33
"""Upload an entire inventory. CLOBBERS CONTENT
34
35
db -- LMFDB connection to inventory database
36
master_file_name -- path to report tool database structure file
37
list_file_name -- path to file containing list of all additional inventory info files
38
fresh -- set to sync tables according to whether this is a fresh or new upload
39
"""
40
#For a complete upload is more logical to fill things in thing by thing
41
#so we do all the db's first, then the collections and finish with the additional description
42
43
decoder = json.JSONDecoder()
44
structure_dat = decoder.decode(read_file(master_file_name))
45
46
inv.log_dest.info("_____________________________________________________________________________________________")
47
inv.log_dest.info("Processing autogenerated inventory")
48
n_dbs = len(structure_dat.keys())
49
progress_tracker = 0
50
51
for DB_name in structure_dat:
52
progress_tracker += 1
53
inv.log_dest.info("Uploading " + DB_name+" ("+str(progress_tracker)+" of "+str(n_dbs)+')')
54
invc.set_db(db, DB_name, DB_name)
55
56
for coll_name in structure_dat[DB_name]:
57
inv.log_dest.info(" Uploading collection "+coll_name)
58
orphaned_keys = upload_collection_structure(db, DB_name, coll_name, structure_dat, fresh=fresh)
59
if len(orphaned_keys) != 0:
60
with open('Orph_'+DB_name+'_'+coll_name+'.json', 'w') as file:
61
file.write(json.dumps(orphaned_keys))
62
inv.log_dest.info(" Orphans written to Orph_"+ DB_name+'_'+coll_name+'.json')
63
64
inv.log_dest.info("_____________________________________________________________________________________________")
65
inv.log_dest.info("Processing additional inventory")
66
file_list = read_list(list_file_name)
67
last_db = ''
68
progress_tracker = 0
69
for file in file_list:
70
data = decoder.decode(read_file(file))
71
record_name = ih.get_description_key(file)
72
DB_name = record_name[0]
73
if DB_name != last_db:
74
inv.log_dest.info("Uploading " + DB_name+" ("+str(progress_tracker)+" of <="+str(n_dbs)+')')
75
last_db = DB_name
76
progress_tracker += 1
77
coll_name = record_name[1]
78
inv.log_dest.info(" Uploading collection "+coll_name)
79
80
upload_collection_description(db, DB_name, coll_name, data)
81
82
83
def upload_collection_from_files(db, db_name, coll_name, master_file_name, json_file_name, fresh=False):
84
"""Freshly upload inventory for a single collection. CLOBBERS CONTENT
85
86
db -- LMFDB connection to inventory database
87
db_name -- Name of database this collection is in
88
coll_name -- Name of collection to upload
89
master_file_name -- path to report tool database structure file
90
json_file_name -- path to file containing additional inventory data
91
fresh -- set to skip some syncing if this is a fresh or new upload
92
"""
93
94
decoder = json.JSONDecoder()
95
96
inv.log_dest.info("Uploading collection structure for "+coll_name)
97
structure_data = decoder.decode(read_file(master_file_name))
98
99
#Do we need to keep the orphans?
100
#orphaned_keys = upload_collection_structure(db, db_name, coll_name, structure_data, fresh=fresh)
101
upload_collection_structure(db, db_name, coll_name, structure_data, fresh=fresh)
102
103
inv.log_dest.info("Uploading collection description for "+coll_name)
104
data = decoder.decode(read_file(json_file_name))
105
upload_collection_description(db, db_name, coll_name, data, fresh=fresh)
106
107
def upload_collection_description(db, db_name, coll_name, data, fresh=False):
108
"""Upload the additional description
109
110
db -- LMFDB connection to inventory database
111
db_name -- Name of database this collection is in
112
coll_name -- Name of collection to upload
113
data -- additional data as json object for this collection
114
fresh -- whether to delete existing info (otherwise extra description will be added, overwriting if required, but anything absent from new info will not be clobbered
115
116
Note this only uploads actual data. All mandatory fields should have been filled by the structure upload
117
"""
118
119
try:
120
db_entry = invc.get_db_id(db, db_name)
121
_c_id = invc.get_coll_id(db, db_entry['id'], coll_name)
122
if not (db_entry['exist'] and _c_id['exist']):
123
#All dbs/collections should have been added from the struc: if not is error
124
inv.log_dest.error("Cannot add descriptions, db or collection not found")
125
return
126
except Exception as e:
127
inv.log_dest.error("Failed to refresh collection "+str(e))
128
129
try:
130
split_data = extract_specials(data)
131
#Insert the notes and info fields into the collection
132
try:
133
notes_data = split_data[inv.STR_NOTES]
134
notes_data = ih.blank_all_empty_fields(notes_data)
135
inv.log_dest.debug(notes_data)
136
except Exception:
137
notes_data = None
138
try:
139
info_data = split_data[inv.STR_INFO]
140
info_data = ih.blank_all_empty_fields(info_data)
141
inv.log_dest.debug(info_data)
142
except Exception:
143
info_data = None
144
_c_id = invc.set_coll(db, db_entry['id'], coll_name, coll_name, notes_data, info_data)
145
except Exception as e:
146
inv.log_dest.error("Failed to refresh collection info "+str(e))
147
148
try:
149
for field in split_data['data']:
150
dat = split_data['data'][field]
151
if not ih.is_record_name(dat):
152
inv.log_dest.info(" Processing "+field)
153
invc.set_field(db, _c_id['id'], field, dat, type='human')
154
else:
155
inv.log_dest.info(" Processing record "+field)
156
#Data may not actually contain the name or description fields
157
rec_set = {'hash':field}
158
try:
159
rec_set['name'] = dat['name']
160
except Exception:
161
pass
162
try:
163
rec_set['description'] = dat['description']
164
except Exception:
165
pass
166
invc.set_record(db, _c_id['id'], rec_set, type='human')
167
168
except Exception as e:
169
inv.log_dest.error("Failed to refresh collection "+str(e))
170
171
def read_file(filename):
172
"""Read entire file contents """
173
with open(filename, 'r') as in_file:
174
dat = in_file.read()
175
return dat
176
177
def read_list(listfile):
178
"""Read file line-wise into list of lines """
179
with open(listfile, 'r') as in_file:
180
lines = in_file.read().splitlines()
181
return lines
182
183
#Initial uploader routines ---------------------------------------------------------------
184
185
def fresh_upload(master_file_name, list_file_name):
186
"""Delete existing data and upload a fresh copy.
187
CLOBBERS ALL EXISTING CONTENT
188
189
Arguments:
190
191
- master_file_name -- path to structure file from report tool (e.g. lmfdb_structure.json)
192
193
- list_file_name -- path to file containing names of all json files to upload (one per collection)
194
"""
195
got_client = inv.setup_internal_client(editor=True)
196
if not got_client:
197
inv.log_dest.error("Cannot connect to db")
198
return
199
db = inv.int_client[inv.get_inv_db_name()]
200
201
#DELETE all existing inventory!!!
202
delete_all_tables(db)
203
204
upload_from_files(db, master_file_name, list_file_name, fresh=True)
205
recreate_rollback_table(db, MAX_SZ)
206
207
def fresh_upload_coll(db_name, coll_name, master_file_name, json_file_name):
208
"""Delete existing data and upload a fresh copy for a single collection.
209
CLOBBERS ALL EXISTING CONTENT FOR THIS COLLECTION
210
211
Arguments:
212
213
- db_name -- name of database to refresh
214
- coll_name -- name of collection to refresh
215
- master_file_name -- path to structure file from report tool (entire or single collection)
216
- json_file_name -- path to additional json file for this collection
217
"""
218
got_client = inv.setup_internal_client(editor=True)
219
if not got_client:
220
inv.log_dest.error("Cannot connect to db")
221
return
222
db = inv.int_client[inv.get_inv_db_name()]
223
224
delete_by_collection(db, db_name, coll_name)
225
upload_collection_from_files(db, db_name, coll_name, master_file_name, json_file_name, fresh=True)
226
227