wwpdb.apps.msgmodule 0.176.2__tar.gz → 0.177__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.
Files changed (31) hide show
  1. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/PKG-INFO +3 -1
  2. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/setup.py +2 -0
  3. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/__init__.py +1 -1
  4. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/depict/MessagingTemplates.py +47 -4
  5. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/io/MessagingIo.py +32 -6
  6. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/util/AutoMessage.py +6 -0
  7. wwpdb_apps_msgmodule-0.177/wwpdb/apps/msgmodule/util/DaInternalDb.py +167 -0
  8. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/util/ExtractMessage.py +2 -2
  9. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/webapp/MessagingWebApp.py +85 -14
  10. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb.apps.msgmodule.egg-info/PKG-INFO +3 -1
  11. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb.apps.msgmodule.egg-info/SOURCES.txt +1 -0
  12. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb.apps.msgmodule.egg-info/requires.txt +2 -0
  13. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/README.md +0 -0
  14. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/setup.cfg +0 -0
  15. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/__init__.py +0 -0
  16. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/__init__.py +0 -0
  17. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/depict/MessagingDepict.py +0 -0
  18. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/depict/__init__.py +0 -0
  19. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/io/DateUtil.py +0 -0
  20. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/io/EmHeaderUtils.py +0 -0
  21. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/io/MessagingDataExport.py +0 -0
  22. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/io/MessagingDataImport.py +0 -0
  23. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/io/__init__.py +0 -0
  24. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/models/Message.py +0 -0
  25. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/models/__init__.py +0 -0
  26. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/util/__init__.py +0 -0
  27. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/webapp/__init__.py +0 -0
  28. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb/apps/msgmodule/webapp/wsgi.py +0 -0
  29. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb.apps.msgmodule.egg-info/dependency_links.txt +0 -0
  30. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb.apps.msgmodule.egg-info/not-zip-safe +0 -0
  31. {wwpdb_apps_msgmodule-0.176.2 → wwpdb_apps_msgmodule-0.177}/wwpdb.apps.msgmodule.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wwpdb.apps.msgmodule
3
- Version: 0.176.2
3
+ Version: 0.177
4
4
  Summary: wwPDB messaging module
5
5
  Home-page: https://github.com/rcsb/py-wwpdb_apps_ann_tasks_v2
6
6
  Author: Ezra Peisach
@@ -15,8 +15,10 @@ Classifier: Programming Language :: Python :: 2.7
15
15
  Classifier: Programming Language :: Python :: 3
16
16
  Classifier: Programming Language :: Python :: 3.6
17
17
  Classifier: Programming Language :: Python :: 3.7
18
+ Requires-Dist: oslo.concurrency
18
19
  Requires-Dist: wwpdb.io
19
20
  Requires-Dist: wwpdb.utils.config~=0.39
21
+ Requires-Dist: wwpdb.utils.db
20
22
  Requires-Dist: wwpdb.utils.session
21
23
  Requires-Dist: wwpdb.utils.wf>=0.8
22
24
  Requires-Dist: mmcif
@@ -42,8 +42,10 @@ setup(
42
42
  ],
43
43
  #
44
44
  install_requires=[
45
+ "oslo.concurrency",
45
46
  "wwpdb.io",
46
47
  "wwpdb.utils.config ~= 0.39",
48
+ "wwpdb.utils.db",
47
49
  "wwpdb.utils.session",
48
50
  "wwpdb.utils.wf >= 0.8",
49
51
  "mmcif",
@@ -2,4 +2,4 @@ __docformat__ = "restructuredtext en"
2
2
  __author__ = "Ezra Peisach"
3
3
  __email__ = "ezra.peisach@rcsb.org"
4
4
  __license__ = "Apache 2.0"
5
- __version__ = "0.176.2"
5
+ __version__ = "0.177"
@@ -30,6 +30,7 @@
30
30
  # 2022-01-26 CS update template
31
31
  # 2022-02-27 CS add template for Map-only withdrawn
32
32
  # 2023-10-20 CS add/modify various templates for superseding entry release, EM model-only and map-only
33
+ # 2024-09-09 CS add templates msgTmplt_reminder_auth_to_rel and msgTmplt_reminder_auth_to_rel_em
33
34
  ##
34
35
  """
35
36
  Convenience class to serve as source of message templates for dynamic population
@@ -165,6 +166,48 @@ In accordance with wwPDB policies (http://www.wwpdb.org/documentation/policy), i
165
166
 
166
167
  Thank you for your attention.
167
168
 
169
+ %(msg_closing)s
170
+ """
171
+
172
+ msgTmplt_reminder_auth_to_rel = """Dear Depositors,
173
+
174
+ This message is to inform you that your entry %(accession_ids)s (Deposition ID %(identifier)s) is scheduled for release. The entry is entitled:
175
+
176
+ %(horiz_line)s
177
+ %(title)s
178
+ %(horiz_line)s
179
+
180
+ Entry authors:
181
+
182
+ %(entry_authors_newline_list)s
183
+
184
+ Your entry was deposited with a request for immediate release.
185
+
186
+ As we have not heard from you since we sent you the validation report and processed files on %(outbound_rprt_date)s, we consider your entry has been approved.
187
+
188
+ Unless we hear from you otherwise, your entry will be set for release next week, in accordance with wwPDB policies (http://www.wwpdb.org/documentation/policy).
189
+
190
+ %(msg_closing)s
191
+ """
192
+
193
+ msgTmplt_reminder_auth_to_rel_em = """Dear Depositors,
194
+
195
+ This message is to inform you that your entry %(accession_ids)s (Deposition ID %(identifier)s) is scheduled for release. The entry is entitled:
196
+
197
+ %(horiz_line)s
198
+ %(em_title)s
199
+ %(horiz_line)s
200
+
201
+ Entry authors:
202
+
203
+ %(em_entry_authors_newline_list)s
204
+
205
+ Your entry was deposited with a request for immediate release.
206
+
207
+ As we have not heard from you since we sent you the validation report and processed files on %(outbound_rprt_date)s, we consider your entry has been approved.
208
+
209
+ Unless we hear from you otherwise, your entry will be set for release next week, in accordance with wwPDB policies (http://www.wwpdb.org/documentation/policy).
210
+
168
211
  %(msg_closing)s
169
212
  """
170
213
 
@@ -351,7 +394,7 @@ Thank you for your attention.
351
394
 
352
395
  msgTmplt_mapOnly_authStatus_em = """Dear Depositors,
353
396
 
354
- Your %(accession_ids)s which corresponds to Deposition ID %(identifier)s has been annotated and the status is now AUTH.
397
+ Your %(accession_ids)s which corresponds to Deposition ID %(identifier)s has been annotated and the status is now %(status_code_em_map)s.
355
398
 
356
399
  %(horiz_line)s
357
400
  %(em_title)s
@@ -410,7 +453,7 @@ Thank you for your attention.
410
453
 
411
454
  Please acknowledge receipt of this message.
412
455
 
413
- This message is to inform you that your %(accession_ids)s (Deposition ID %(identifier)s) %(is_are)sstill awaiting your input. The entry is entitled:
456
+ This message is to inform you that your %(accession_ids)s (Deposition ID %(identifier)s) %(is_are)s still awaiting your input. The entry is entitled:
414
457
 
415
458
  %(horiz_line)s
416
459
  %(em_title)s
@@ -418,8 +461,8 @@ This message is to inform you that your %(accession_ids)s (Deposition ID %(ident
418
461
 
419
462
  We have not heard from you since we sent you the %(vldtn_rprt)sprocessed files on %(outbound_rprt_date_em)s. Please respond to the questions raised in our previous correspondence as soon as possible.
420
463
 
421
- In accordance with wwPDB policies (http://www.wwpdb.org/documentation/policy.html), if we find a publication describing the %(entry_entries_comma)s%(it_they_lcase)swill be released%(caveat_records)s.
422
- If after %(expire_date_em_map)s (one year from the deposition date) we are unable to find a publication describing%(this_these)s%(entry_entries_comma)s the%(entry_entries)smay be withdrawn if there remain outstanding issues, otherwise the%(entry_entries)swill be released.
464
+ In accordance with wwPDB policies (http://www.wwpdb.org/documentation/policy.html), if we find a publication describing the %(entry_entries_comma)s %(it_they_lcase)s will be released %(caveat_records)s.
465
+ If after %(expire_date_em_map)s (one year from the deposition date) we are unable to find a publication describing %(this_these)s %(entry_entries_comma)s the %(entry_entries)s may be withdrawn if there remain outstanding issues, otherwise the %(entry_entries)s will be released.
423
466
 
424
467
  Thank you for your attention.
425
468
 
@@ -124,6 +124,8 @@
124
124
  # 2023-11-20 EP Add anyUnactionApprovalWithoutCorrection() to determine if any pendingapproval without corrections that need to be acted upon
125
125
  # 2023-11-23 EP autoMsg() add support for explicit-approved autogenerated message
126
126
  # 2024-04-04 CS Add context_type to autoMsg() and sendSingle() to match frontend message-to-depositor drop-down list
127
+ # 2024-09-09 CS Add process to send reminder on AUTH entry deposited as REL
128
+ # 2024-09-18 CS Change statusCode selection in __getDefaultMsgTmpltType for map-only entries
127
129
  ##
128
130
  """
129
131
  Class to manage persistence/retrieval of messaging data
@@ -1407,7 +1409,13 @@ class MessagingIo(object):
1407
1409
  isNote = True
1408
1410
  # Need all ids
1409
1411
  accstr = templateDict["accession_ids"]
1410
- subject = "ARCHIVED: Still awaiting feedback for " + accstr
1412
+ subject = "REMINDER: Still awaiting feedback for " + accstr
1413
+ elif p_tmpltType == "reminder-auth-to-rel": # CS 2024-09-09 add process to send reminder on AUTH entry deposited as REL
1414
+ msgTmplt = MessagingTemplates.msgTmplt_reminder_auth_to_rel_em if p_isEmdbEntry else MessagingTemplates.msgTmplt_reminder_auth_to_rel
1415
+ attachFiles = False
1416
+ isNote = True
1417
+ accstr = templateDict["accession_ids"]
1418
+ subject = "REMINDER: Upcoming release of " + accstr
1411
1419
  else:
1412
1420
  logger.error("Unknown message template %s", p_tmpltType)
1413
1421
  msgTmplt = "This is an unknown message template."
@@ -4871,7 +4879,7 @@ class MsgTmpltHlpr(object):
4871
4879
  If it is an EM map only entry --> if _pdbx_database_status.status_code= AUTH -> launch mapOnly-AuthStatus_letter_template
4872
4880
  """
4873
4881
 
4874
- # CS 2023-11-06 start change logic for default template, primary on statusCode dependency, impact EM entries only
4882
+ # before 2023-11-06 start
4875
4883
  # if self.__emDeposition:
4876
4884
  # statusCode = self.__statusCodeEmMap
4877
4885
  # else:
@@ -4880,15 +4888,33 @@ class MsgTmpltHlpr(object):
4880
4888
  # statusCode = self.__postRelStatus
4881
4889
  # else:
4882
4890
  # statusCode = self.__statusCode
4883
- if self.__postRelStatus and len(self.__postRelStatus) > 1:
4891
+ # before 2023-11-06 end
4892
+
4893
+ # CS 2023-11-06 start change logic for default template, primary on statusCode dependency, impact EM entries only
4894
+ # if self.__postRelStatus and len(self.__postRelStatus) > 1:
4895
+ # statusCode = self.__postRelStatus
4896
+ # elif self.__statusCode and len(self.__statusCode) > 1:
4897
+ # statusCode = self.__statusCode
4898
+ # elif self.__emDeposition:
4899
+ # statusCode = self.__statusCodeEmMap
4900
+ # else:
4901
+ # pass
4902
+ # CS 2023-11-06 end
4903
+
4904
+ # CS 2024-09-18 start change logic again for statusCode on map-only entries
4905
+ statusCode = None
4906
+ if self.__emMapOnly and self.__emDeposition:
4907
+ statusCode = self.__statusCodeEmMap
4908
+ elif self.__postRelStatus and len(self.__postRelStatus) > 1:
4884
4909
  statusCode = self.__postRelStatus
4885
4910
  elif self.__statusCode and len(self.__statusCode) > 1:
4886
4911
  statusCode = self.__statusCode
4887
- elif self.__emDeposition:
4888
- statusCode = self.__statusCodeEmMap
4889
4912
  else:
4890
4913
  pass
4891
- # CS 2023-11-06 end
4914
+ # CS 2024-09-18 end
4915
+
4916
+ logger.info("CStrack+++ statusCode = %s", statusCode)
4917
+ logger.info("CStrack+++ self.__emDeposition = %s, self.__emMapOnly = %s", self.__emDeposition, self.__emMapOnly)
4892
4918
 
4893
4919
  if statusCode and len(statusCode) > 1:
4894
4920
  if statusCode == "HPUB" or statusCode == "HOLD":
@@ -3,6 +3,8 @@
3
3
  # Date: 28-Jun-2019 E. Peisach
4
4
  #
5
5
  # Update:
6
+ # 2024-09-09 CS Add function to send reminder on AUTH entry deposited as REL
7
+ ##
6
8
  """
7
9
  Support for automatic scripts to send template drive email messages and archive in normal message stream/notes
8
10
  Auto messages are archived in notes-from-annotator
@@ -63,6 +65,10 @@ class AutoMessage(object):
63
65
  """ Sends a reminder that depositor has not responded to validation report """
64
66
  self._sendReminderBulk(depidlist, p_tmplt="reminder")
65
67
 
68
+ def sendRemindAuthToRel(self, depidlist): # CS 2024-09-09 Add function to send reminder on AUTH entry deposited as REL
69
+ """ Sends a reminder that depositor has not responded to validation report on AUTH entries deposited as REL """
70
+ self._sendReminderBulk(depidlist, p_tmplt="reminder-auth-to-rel")
71
+
66
72
  def sendImplicitApproved(self, depidlist):
67
73
  self._sendReminderBulk(depidlist, p_tmplt="approval-impl") # CS 2024-04-04 change implicit-approved to approval-impl to match frontend drop-down
68
74
 
@@ -0,0 +1,167 @@
1
+ # =============================================================================
2
+ # Author: Chenghua Shao
3
+ # Date: 2024-08-30
4
+ # Updates:
5
+ #
6
+ # =============================================================================
7
+ """
8
+ DA_INTERNAL database utility
9
+ """
10
+
11
+ from wwpdb.utils.db.MyConnectionBase import MyConnectionBase
12
+ import logging
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class DaInternalDb(object):
18
+ """DA_INTERNAL DB class for data lookup
19
+
20
+ Args:
21
+ object (_type_): object
22
+ """
23
+ def __init__(self, siteId=None):
24
+ """Initiator
25
+
26
+ Args:
27
+ siteId (_type_, optional): SITE ID. Defaults to None that will use the SITE ID of the current server.
28
+ """
29
+ self.__mydb = None
30
+ self.__siteId = siteId
31
+ self.__open()
32
+
33
+ def __del__(self):
34
+ """Finalizer. Close DB connection when all references to the object have been deleted.
35
+ """
36
+ self.__close()
37
+
38
+ def __open(self, resource="DA_INTERNAL"):
39
+ """Open DB connection
40
+
41
+ Args:
42
+ resource (str, optional): DB name. Defaults to "DA_INTERNAL".
43
+
44
+ Returns:
45
+ _type_: True/False for DB connection
46
+ """
47
+ self.__mydb = MyConnectionBase(siteId=self.__siteId)
48
+ self.__mydb.setResource(resourceName=resource)
49
+ ok = self.__mydb.openConnection()
50
+ if not ok:
51
+ logger.error("Could not open resourve %s", resource)
52
+ self.__mydb = None
53
+ return False
54
+
55
+ return True
56
+
57
+ def __close(self):
58
+ """Proper DB closure
59
+ """
60
+ if self.__mydb:
61
+ self.__mydb.closeConnection()
62
+ self.__mydb = None
63
+
64
+ def run(self, query):
65
+ """Simplified query runner
66
+
67
+ Args:
68
+ query (_type_): Full text of a query
69
+
70
+ Returns:
71
+ _type_: raw query results as tuple of tuples, e.g. ((1,2),(3,4))
72
+ """
73
+ cur = self.__mydb.getCursor()
74
+ cur.execute(query)
75
+ rows = cur.fetchall()
76
+ cur.close()
77
+ return rows
78
+
79
+ def verifyDepId(self, dep_id):
80
+ """Verify if an id is deposition id
81
+
82
+ Args:
83
+ dep_id (_type_): presumed dep id input
84
+
85
+ Returns:
86
+ _type_: True/False
87
+ """
88
+ query = "select structure_id from rcsb_status where structure_id = '%s'" % dep_id
89
+ rows = self.run(query)
90
+ if rows:
91
+ return True
92
+ else:
93
+ return False
94
+
95
+ def verifyPdbId(self, pdb_id):
96
+ """Verify if an id is PDB ID
97
+
98
+ Args:
99
+ pdb_id (_type_): presumed PDB id input
100
+
101
+ Returns:
102
+ _type_: True/False
103
+ """
104
+ query = "select structure_id from rcsb_status where pdb_id = '%s'" % pdb_id
105
+ rows = self.run(query)
106
+ if rows:
107
+ return True
108
+ else:
109
+ return False
110
+
111
+ def verifyEmdbId(self, emdb_id):
112
+ """Verify if an id is EMDB ID
113
+
114
+ Args:
115
+ emdb_id (_type_): presumed EMDB ID input
116
+
117
+ Returns:
118
+ _type_: True/False
119
+ """
120
+ query = "select structure_id from database_2 where database_id = 'EMDB' and database_code = '%s'" % emdb_id
121
+ rows = self.run(query)
122
+ if rows:
123
+ return True
124
+ else:
125
+ return False
126
+
127
+ def convertPdbIdToDepId(self, pdb_id):
128
+ """Convert PDB ID to deposition id
129
+
130
+ Args:
131
+ pdb_id (_type_): presumed PDB ID
132
+
133
+ Returns:
134
+ _type_: valid deposition id at this site, or None
135
+ """
136
+ query = "select structure_id from rcsb_status where pdb_id = '%s'" % pdb_id
137
+ rows = self.run(query)
138
+ if rows:
139
+ return rows[0][0]
140
+ else:
141
+ return None
142
+
143
+ def convertEmdbIdToDepId(self, emdb_id):
144
+ """Convert EMDB ID to deposition id
145
+
146
+ Args:
147
+ pdb_id (_type_): presumed EMDB ID
148
+
149
+ Returns:
150
+ _type_: valid deposition id at this site, or None
151
+ """
152
+ query = "select structure_id from database_2 where database_id = 'EMDB' and database_code = '%s'" % emdb_id
153
+ rows = self.run(query)
154
+ if rows:
155
+ return rows[0][0]
156
+ else:
157
+ return None
158
+
159
+
160
+ if __name__ == "__main__":
161
+ # Minimal temporary testing, cannot develop unit test because the IDs at the test sites are cleaned up regularly.
162
+ db_da_internal = DaInternalDb()
163
+ print(db_da_internal.verifyDepId("D_1000272951"))
164
+ print(db_da_internal.verifyPdbId("8GI8"))
165
+ print(db_da_internal.verifyEmdbId("EMD-40062"))
166
+ print(db_da_internal.convertPdbIdToDepId("8GI8"))
167
+ print(db_da_internal.convertEmdbIdToDepId("EMD-40062"))
@@ -6,7 +6,7 @@
6
6
  # 2023-11-10 CS Refactor code to add general process to parse message file; Add functions to retrieve datetime of last messages of various type.
7
7
  # 2023-11-23 EP Add getApprovalNoCorrectSubjects() and getPendingDepositorMessages()
8
8
  # 2024-04-04 CS Use context_type and context_value to find target message, and default to subject/title parsing as was used previously.
9
- #
9
+ # 2024-09-09 CS Update getLastAutoReminderDatetime() to include search on reminder-auth-to-rel
10
10
  ##
11
11
  """
12
12
  Support for automatic extracting information from send messages
@@ -256,7 +256,7 @@ class ExtractMessage(object):
256
256
  ret = None
257
257
  self.__readMsgFile(depid, contentType="notes-from-annotator", b_use_cache=b_use_cache, test_folder=test_folder)
258
258
  if len(self.__lc) >= 1:
259
- ret_by_context_type = self.__selectLastMsgByContextType(["reminder"]) # CS 2024-04-04 search by context_type first
259
+ ret_by_context_type = self.__selectLastMsgByContextType(["reminder", "reminder-auth-to-rel"]) # CS 2024-09-09 add reminder-auth-to-rel
260
260
  if ret_by_context_type:
261
261
  ret = ret_by_context_type
262
262
  else:
@@ -37,6 +37,7 @@
37
37
  # 2016-09-14 ZF Added __checkGroupDeposition() function to support for group deposition
38
38
  # 2023-11-20 EP Added __checkAnyApprovalFlags() and set approriate database flags if set
39
39
  # 2024-04-04 CS Add process on context_type/context_value of message-to-depositor recorded by frontend JavaScript and passed here through wsgi message submit URL
40
+ # 2024-08-30 CS Add MessagingWebAppWorker._verifyOrConvertId() used by _propagateMsg("archive") to archive messages by PDB or EMDB IDs
40
41
  ##
41
42
  """
42
43
  wwPDB Messaging web request and response processing modules.
@@ -73,6 +74,7 @@ from wwpdb.apps.msgmodule.depict.MessagingDepict import MessagingDepict
73
74
  from wwpdb.apps.msgmodule.io.MessagingIo import MessagingIo
74
75
  from wwpdb.utils.wf.dbapi.StatusDbApi import StatusDbApi
75
76
  from wwpdb.apps.msgmodule.models.Message import Message
77
+ from wwpdb.apps.msgmodule.util.DaInternalDb import DaInternalDb
76
78
 
77
79
  #
78
80
  # from wwpdb.apps.msgmodule.utils.WfTracking import WfTracking
@@ -208,6 +210,9 @@ class MessagingWebAppWorker(object):
208
210
  # self.__rltvSessionPath = None
209
211
  self.__siteId = str(self.__reqObj.getValue("WWPDB_SITE_ID"))
210
212
  # self.__cI = ConfigInfo(self.__siteId)
213
+
214
+ # CS 2024-08-30 create class var for status DB api because such api is used multiple times
215
+ self.statusApi = StatusDbApi(siteId=self.__siteId, verbose=self.__verbose, log=self.__lfh)
211
216
  #
212
217
  # Added by ZF
213
218
  #
@@ -881,8 +886,8 @@ class MessagingWebAppWorker(object):
881
886
  self.__reqObj.setValue("groupid", depId)
882
887
  return
883
888
  #
884
- statusApi = StatusDbApi(siteId=self.__siteId, verbose=self.__verbose, log=self.__lfh)
885
- groupId = statusApi.getGroupId(depId)
889
+ # statusApi = StatusDbApi(siteId=self.__siteId, verbose=self.__verbose, log=self.__lfh)
890
+ groupId = self.statusApi.getGroupId(depId)
886
891
  if groupId:
887
892
  self.__reqObj.setValue("groupid", groupId)
888
893
  #
@@ -1041,16 +1046,16 @@ class MessagingWebAppWorker(object):
1041
1046
  #
1042
1047
  # Added by ZF
1043
1048
  #
1044
- statusApi = StatusDbApi(siteId=self.__siteId, verbose=self.__verbose, log=self.__lfh)
1049
+ # statusApi = StatusDbApi(siteId=self.__siteId, verbose=self.__verbose, log=self.__lfh)
1045
1050
  groupId = str(self.__reqObj.getValue("groupid"))
1046
1051
  if groupId:
1047
- statusApi.runUpdate(table="batch_user_data", where={"dep_set_id": groupId.upper()}, data={"notify": p_status})
1048
- entryList = statusApi.getEntryIdList(groupId=groupId)
1052
+ self.statusApi.runUpdate(table="batch_user_data", where={"dep_set_id": groupId.upper()}, data={"notify": p_status})
1053
+ entryList = self.statusApi.getEntryIdList(groupId=groupId)
1049
1054
  for entry in entryList:
1050
- statusApi.runUpdate(table="deposition", where={"dep_set_id": entry}, data={"notify": p_status})
1055
+ self.statusApi.runUpdate(table="deposition", where={"dep_set_id": entry}, data={"notify": p_status})
1051
1056
  #
1052
1057
  else:
1053
- statusApi.runUpdate(table="deposition", where={"dep_set_id": p_depId.upper()}, data={"notify": p_status})
1058
+ self.statusApi.runUpdate(table="deposition", where={"dep_set_id": p_depId.upper()}, data={"notify": p_status})
1054
1059
  #
1055
1060
  bSuccess = True
1056
1061
  except: # noqa: E722 pylint: disable=bare-except
@@ -1221,6 +1226,58 @@ class MessagingWebAppWorker(object):
1221
1226
  def _forwardMsg(self):
1222
1227
  return self._propagateMsg("forward")
1223
1228
 
1229
+ def _verifyOrConvertId(self, id_to_check): # CS 2024-08-30
1230
+ """Verify whether an id is valid site-specific deposition id (D_##...) through DA_INTERNAL DB.
1231
+ If the id is not a deposition id, verify whether it's PDB ID or EMDB ID, and if so, attempt to convert
1232
+ such ids to valid deposition id, which aims to handle message archving based on PDB or EMDB ID.
1233
+ The verification and conversion is site-id specific, and do NOT work cross sites or corss site-ids.
1234
+ Because DA_INTERNAL DB doesn't record pdb extension id at the time this function is created,
1235
+ extended pdb id is handled by truncate the last 4 characters for temporary use.
1236
+
1237
+ Args:
1238
+ id (_type_): Deposition id, PDB ID, extended PDB ID, or EMDB ID, or any input text string as ID
1239
+
1240
+ Returns:
1241
+ _type_: verfied or converted deposition id at the same site, or 'None' for invalid id input
1242
+ """
1243
+ id_to_check = id_to_check.strip()
1244
+ if not id_to_check:
1245
+ return None
1246
+
1247
+ logger.info("verify or convert id: %s through DA_INTERNAL DB", id_to_check)
1248
+ db_da_internal = DaInternalDb() # connect to DA_INTERNAL DB utility
1249
+ id_to_check = id_to_check.upper()
1250
+ if id_to_check.startswith("D_"): # format of deposition id
1251
+ dep_id = id_to_check
1252
+ if db_da_internal.verifyDepId(dep_id):
1253
+ logger.debug("%s is valid deposition id at this site", id_to_check)
1254
+ return dep_id # return the input id itself is vefified
1255
+ else:
1256
+ return None
1257
+ elif id_to_check.startswith("EMD-"): # format of EMDB ID
1258
+ emdb_id = id_to_check
1259
+ if db_da_internal.verifyEmdbId(emdb_id):
1260
+ logger.debug("%s is valid EMDB ID, convert it to deposition id", id_to_check)
1261
+ return db_da_internal.convertEmdbIdToDepId(emdb_id) # EMDB->dep conversion
1262
+ else:
1263
+ return None
1264
+ elif id_to_check.startswith("PDB_0000") and len(id_to_check) == 12: # format of extended PDB ID
1265
+ pdb_id = id_to_check[-4:] # truncate the last 4 chars as temporary solution
1266
+ if db_da_internal.verifyPdbId(pdb_id):
1267
+ logger.debug("%s is valid extended PDB ID, convert it to deposition id", id_to_check)
1268
+ return db_da_internal.convertPdbIdToDepId(pdb_id) # PDB->dep conversion
1269
+ else:
1270
+ return None
1271
+ elif len(id_to_check) == 4: # format of PDB ID
1272
+ pdb_id = id_to_check
1273
+ if db_da_internal.verifyPdbId(pdb_id):
1274
+ logger.debug("%s is valid PDB ID, convert it to deposition id", id_to_check)
1275
+ return db_da_internal.convertPdbIdToDepId(pdb_id) # PDB->dep conversion
1276
+ else:
1277
+ return None
1278
+ else: # wrong id input
1279
+ return None
1280
+
1224
1281
  def _propagateMsg(self, actionType):
1225
1282
  """
1226
1283
  :Helpers:
@@ -1229,6 +1286,7 @@ class MessagingWebAppWorker(object):
1229
1286
 
1230
1287
  """
1231
1288
  #
1289
+ logger.info("start _propagateMsg with actionType = %s", actionType)
1232
1290
  #
1233
1291
  self.__getSession()
1234
1292
  # depId = self.__reqObj.getValue("entry_id") # getValue("identifier")
@@ -1278,17 +1336,29 @@ class MessagingWebAppWorker(object):
1278
1336
  #
1279
1337
  # Added by ZF
1280
1338
  #
1281
- statusApi = StatusDbApi(siteId=self.__siteId, verbose=self.__verbose, log=self.__lfh)
1339
+ # statusApi = StatusDbApi(siteId=self.__siteId, verbose=self.__verbose, log=self.__lfh)
1340
+
1341
+ bOk = False # initiate bOk in case of exit from loop below
1282
1342
  for depId in depIdLst:
1283
- self.__reqObj.setValue("identifier", depId) # setting here for downstream processing
1343
+ depId = depId.strip()
1344
+ logger.debug("start processing %s", depId)
1345
+ depId_2 = self._verifyOrConvertId(depId) # CS 2024-08-30 verify dep id or convert PDB/EMDB ID to dep id for archiving
1346
+ logger.debug("verified or converted id %s", depId_2)
1347
+
1348
+ if not depId_2:
1349
+ logger.error("fail to verify or convert the input id %s", depId) # skip unverified id
1350
+ rtrnDict["success"][depId] = "false"
1351
+ continue
1352
+
1353
+ self.__reqObj.setValue("identifier", depId_2) # setting here for downstream processing
1284
1354
  #
1285
- # Added by ZF
1355
+ # Added by ZF for GroupDep group message
1286
1356
  #
1287
1357
  groupId = ""
1288
- if depId.startswith("G_"):
1289
- groupId = depId
1358
+ if depId_2.startswith("G_"):
1359
+ groupId = depId_2
1290
1360
  else:
1291
- found_groupId = statusApi.getGroupId(depId)
1361
+ found_groupId = self.statusApi.getGroupId(depId_2)
1292
1362
  if found_groupId:
1293
1363
  groupId = found_groupId
1294
1364
  #
@@ -1299,7 +1369,8 @@ class MessagingWebAppWorker(object):
1299
1369
  msgObj = Message.fromReqObj(self.__reqObj, self.__verbose, self.__lfh)
1300
1370
  #
1301
1371
  if self.__verbose:
1302
- logger.info("dep_id is: %s", depId)
1372
+ logger.info("original dep_id is: %s", depId)
1373
+ logger.info("verified/converted dep_id is: %s", depId_2)
1303
1374
  #
1304
1375
  bOk, _bPdbxMdlFlUpdtd, _failedFileRefs = msgingIo.processMsg(msgObj)
1305
1376
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wwpdb.apps.msgmodule
3
- Version: 0.176.2
3
+ Version: 0.177
4
4
  Summary: wwPDB messaging module
5
5
  Home-page: https://github.com/rcsb/py-wwpdb_apps_ann_tasks_v2
6
6
  Author: Ezra Peisach
@@ -15,8 +15,10 @@ Classifier: Programming Language :: Python :: 2.7
15
15
  Classifier: Programming Language :: Python :: 3
16
16
  Classifier: Programming Language :: Python :: 3.6
17
17
  Classifier: Programming Language :: Python :: 3.7
18
+ Requires-Dist: oslo.concurrency
18
19
  Requires-Dist: wwpdb.io
19
20
  Requires-Dist: wwpdb.utils.config~=0.39
21
+ Requires-Dist: wwpdb.utils.db
20
22
  Requires-Dist: wwpdb.utils.session
21
23
  Requires-Dist: wwpdb.utils.wf>=0.8
22
24
  Requires-Dist: mmcif
@@ -22,6 +22,7 @@ wwpdb/apps/msgmodule/io/__init__.py
22
22
  wwpdb/apps/msgmodule/models/Message.py
23
23
  wwpdb/apps/msgmodule/models/__init__.py
24
24
  wwpdb/apps/msgmodule/util/AutoMessage.py
25
+ wwpdb/apps/msgmodule/util/DaInternalDb.py
25
26
  wwpdb/apps/msgmodule/util/ExtractMessage.py
26
27
  wwpdb/apps/msgmodule/util/__init__.py
27
28
  wwpdb/apps/msgmodule/webapp/MessagingWebApp.py
@@ -1,5 +1,7 @@
1
+ oslo.concurrency
1
2
  wwpdb.io
2
3
  wwpdb.utils.config~=0.39
4
+ wwpdb.utils.db
3
5
  wwpdb.utils.session
4
6
  wwpdb.utils.wf>=0.8
5
7
  mmcif