wwpdb.utils.wf 0.43__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.
Files changed (44) hide show
  1. wwpdb/utils/wf/DataSelector.py +106 -0
  2. wwpdb/utils/wf/DataValueContainer.py +158 -0
  3. wwpdb/utils/wf/WfDataObject.py +89 -0
  4. wwpdb/utils/wf/__init__.py +5 -0
  5. wwpdb/utils/wf/dbapi/DbApiUtil.py +237 -0
  6. wwpdb/utils/wf/dbapi/DbCommand.py +456 -0
  7. wwpdb/utils/wf/dbapi/DbConnection.py +156 -0
  8. wwpdb/utils/wf/dbapi/LocalDbApi.py +80 -0
  9. wwpdb/utils/wf/dbapi/StatusDbApi.py +100 -0
  10. wwpdb/utils/wf/dbapi/WFEtime.py +49 -0
  11. wwpdb/utils/wf/dbapi/WfDbApi.py +1237 -0
  12. wwpdb/utils/wf/dbapi/WfTracking.py +114 -0
  13. wwpdb/utils/wf/dbapi/__init__.py +0 -0
  14. wwpdb/utils/wf/dbapi/dbAPI.py +329 -0
  15. wwpdb/utils/wf/plugins/AnnotationUtils.py +1516 -0
  16. wwpdb/utils/wf/plugins/ChemCompUtils.py +262 -0
  17. wwpdb/utils/wf/plugins/DepositUtils.py +46 -0
  18. wwpdb/utils/wf/plugins/DictUtils.py +101 -0
  19. wwpdb/utils/wf/plugins/DpUtils.py +130 -0
  20. wwpdb/utils/wf/plugins/EmUtils.py +427 -0
  21. wwpdb/utils/wf/plugins/FileUtils.py +256 -0
  22. wwpdb/utils/wf/plugins/FormatUtils.py +297 -0
  23. wwpdb/utils/wf/plugins/NmrUtils.py +1122 -0
  24. wwpdb/utils/wf/plugins/PcmCsvUtils.py +74 -0
  25. wwpdb/utils/wf/plugins/PdbxUtils.py +520 -0
  26. wwpdb/utils/wf/plugins/PrdSearchUtils.py +100 -0
  27. wwpdb/utils/wf/plugins/ReportUtils.py +95 -0
  28. wwpdb/utils/wf/plugins/SeqStatsUtils.py +163 -0
  29. wwpdb/utils/wf/plugins/SeqdbUtils.py +276 -0
  30. wwpdb/utils/wf/plugins/UtilsBase.py +52 -0
  31. wwpdb/utils/wf/plugins/ValidationUtils.py +606 -0
  32. wwpdb/utils/wf/plugins/__init__.py +0 -0
  33. wwpdb/utils/wf/process/ActionRegistry.py +514 -0
  34. wwpdb/utils/wf/process/ActionRegistryIo.py +202 -0
  35. wwpdb/utils/wf/process/ProcessRunner.py +276 -0
  36. wwpdb/utils/wf/process/__init__.py +0 -0
  37. wwpdb/utils/wf/schema/WfSchemaMap.py +366 -0
  38. wwpdb/utils/wf/schema/__init__.py +0 -0
  39. wwpdb/utils/wf/schema/database_descriptions.txt +339 -0
  40. wwpdb/utils/wf/schema/mandatory_items.txt +21 -0
  41. wwpdb_utils_wf-0.43.dist-info/METADATA +49 -0
  42. wwpdb_utils_wf-0.43.dist-info/RECORD +44 -0
  43. wwpdb_utils_wf-0.43.dist-info/WHEEL +4 -0
  44. wwpdb_utils_wf-0.43.dist-info/licenses/LICENSE +12 -0
@@ -0,0 +1,106 @@
1
+ ##
2
+ # File: DataSelector.py
3
+ # Date: 5-April-2010
4
+ #
5
+ # Updates:
6
+ #
7
+ ##
8
+ """
9
+ Container for data selection criteria.
10
+
11
+ """
12
+
13
+ __docformat__ = "restructuredtext en"
14
+ __author__ = "John Westbrook"
15
+ __email__ = "jwest@rcsb.rutgers.edu"
16
+ __license__ = "Creative Commons Attribution 3.0 Unported"
17
+ __version__ = "V0.01"
18
+
19
+
20
+ class DataSelector:
21
+ """A container for data selection criteria.
22
+
23
+ A selector defines the following parameters:
24
+
25
+ - targetCategoryName name of category to which selection is applied
26
+ - targetAttributeNameList [attributeName, attributeName,...] the values of the
27
+ attributes in this list will be returned subject to the selection condition.
28
+
29
+ Selection conditions are stored as a list of tuples of name, value and operator:
30
+
31
+ - conditionList [(attributeName,attributeValue,comparisonOp),,...]
32
+
33
+ """
34
+
35
+ def __init__(self):
36
+ super(DataSelector, self).__init__()
37
+ # self.__verbose = False
38
+ # sys.stderr.write("DataSelector.__init_()\n")
39
+ self.__selectorType = None
40
+ #
41
+ self.__targetCategoryName = None
42
+ self.__targetAttributeList = []
43
+ self.__selectConditionList = []
44
+
45
+ def getSelectorType(self):
46
+ """Get the type of selector type. Currently only attribute value selections are supported."""
47
+ return self.__selectorType
48
+
49
+ def setSelectCategoryName(self, categoryName):
50
+ """Set the target category for this selection.
51
+
52
+ Returns:
53
+
54
+ True for success or False otherwise
55
+ """
56
+ try:
57
+ self.__targetCategoryName = categoryName
58
+ return True
59
+ except: # noqa: E722 pylint: disable=bare-except
60
+ return False
61
+
62
+ def getSelectCategoryName(self):
63
+ """Get the taget category for this selection."""
64
+ return self.__targetCategoryName
65
+
66
+ def addSelectAttributeName(self, attributeName):
67
+ """Add an attribute to the list of attributes for this selection.
68
+
69
+ Returns:
70
+
71
+ True for success or False otherwise
72
+ """
73
+ try:
74
+ if attributeName not in self.__targetAttributeList:
75
+ self.__targetAttributeList.append(attributeName)
76
+ self.__selectorType = "attribute"
77
+ return True
78
+ except: # noqa: E722 pylint: disable=bare-except
79
+ return False
80
+
81
+ def getSelectAttributeList(self):
82
+ """Get the list attributes for the current selection"""
83
+ return self.__targetAttributeList
84
+
85
+ def addSelectCondition(self, attributeName, attributeValue, comparisonOp="equal"):
86
+ """Add a selection condition to the current selection.
87
+
88
+ A selection condition contains the following:
89
+ - attributeName in the target category.
90
+ - attributeValue
91
+ - one of the comparison operators (equals, ...)
92
+
93
+ Returns:
94
+
95
+ True for success or False otherwise.
96
+
97
+ """
98
+ try:
99
+ self.__selectConditionList.append((attributeName, attributeValue, comparisonOp))
100
+ return True
101
+ except: # noqa: E722 pylint: disable=bare-except
102
+ return False
103
+
104
+ def getSelectConditionList(self):
105
+ """Get the list selection conditions."""
106
+ return self.__selectConditionList
@@ -0,0 +1,158 @@
1
+ ##
2
+ # File: DataValueContainer.py
3
+ # Date: 28-Mar-2010
4
+ #
5
+ # Updates:
6
+ #
7
+ ##
8
+ """
9
+ Container for data values.
10
+
11
+ """
12
+
13
+ __docformat__ = "restructuredtext en"
14
+ __author__ = "John Westbrook"
15
+ __email__ = "jwest@rcsb.rutgers.edu"
16
+ __license__ = "Creative Commons Attribution 3.0 Unported"
17
+ __version__ = "V0.01"
18
+
19
+ # For python 2/3 compatible comparison with isinstace
20
+ from builtins import str # noqa: UP029,A004
21
+ from datetime import date, datetime
22
+
23
+
24
+ class DataValueContainer:
25
+ """Container for data values.
26
+
27
+ Supported container types include:
28
+ - individual bool, int, float, string, date, or datetime values
29
+ - lists of bool, int, float, string, date, datetime values
30
+
31
+ """
32
+
33
+ def __init__(self):
34
+ super(DataValueContainer, self).__init__()
35
+ # sys.stderr.write("DataValueContainer.__init_()\n")
36
+ #
37
+ self.__valueTypeName = None
38
+ """ A supported data type name such:
39
+ - boolean
40
+ - int or integer
41
+ - float or double
42
+ - string
43
+ - date
44
+ - datetime
45
+ """
46
+ #
47
+ self.__valueType = type(None)
48
+ """ Intrinsic Python type corresponding to the valueTypeName.
49
+
50
+ Types are defined in the Python class `types`.
51
+ """
52
+ #
53
+ self.__containerTypeName = None
54
+ """ Container type setting:
55
+ - value, a single value
56
+ - list, a list/vector of values
57
+ - dict, a dictionary of key/values pairs
58
+
59
+ """
60
+ #
61
+ self.__value = None
62
+
63
+ def isValueValid(self):
64
+ """Performs a sanity type check on the current value and container types.
65
+
66
+ Returns:
67
+
68
+ True if value and container types correspond to the current type settings or False otherwise.
69
+ """
70
+ if self.__containerTypeName == "list":
71
+ if isinstance(self.__value, list):
72
+ for v in self.__value: # noqa: SIM110
73
+ if not isinstance(v, self.__valueType):
74
+ return False
75
+ return True
76
+ return False
77
+ if self.__containerTypeName == "dict":
78
+ if isinstance(self.__value, dict):
79
+ return True
80
+ return False
81
+
82
+ if isinstance(self.__value, self.__valueType):
83
+ return True
84
+ return False
85
+
86
+ def isValueSet(self):
87
+ """Performs a check if the current data value has been set.
88
+
89
+ Returns:
90
+
91
+ True if the value has been set or False otherwise.
92
+
93
+ """
94
+ return self.__value is not None
95
+
96
+ def setValue(self, value):
97
+ self.__value = value
98
+
99
+ def getValue(self):
100
+ return self.__value
101
+
102
+ def setValueTypeName(self, typeName):
103
+ """Set the data type name for the container.
104
+
105
+ Supported types include:
106
+ - boolean
107
+ - int or integer
108
+ - float or double
109
+ - string
110
+ - date
111
+ - datetime -- no TZ aware form -- might need an update
112
+
113
+ Returns:
114
+
115
+ True if the input typeName is a supported type or False otherwise.
116
+ """
117
+ if str(typeName) in ["boolean", "int", "integer", "float", "double", "string", "date", "datetime"]:
118
+ self.__valueTypeName = str(typeName)
119
+ if typeName in ("bool", "boolean"):
120
+ self.__valueType = bool
121
+ elif typeName in ("integer", "int", "float", "double"):
122
+ self.__valueType = int
123
+ elif typeName == "string":
124
+ self.__valueType = str
125
+ elif typeName == "date":
126
+ tt = date(2010, 1, 1)
127
+ self.__valueType = tt.__class__
128
+ elif typeName == "datetime":
129
+ tt = datetime(2010, 1, 1) # noqa: DTZ001
130
+ self.__valueType = tt.__class__
131
+ else:
132
+ return False
133
+ return True
134
+ return False
135
+
136
+ def setContainerTypeName(self, containerName):
137
+ """Set the container type name.
138
+
139
+ Supported container types include:
140
+ - value, a individual value
141
+ - list, list or vector of values
142
+ - dict, dictionary of key,value pairs
143
+
144
+ Returns:
145
+
146
+ True for supported container types or False otherwise.
147
+
148
+ """
149
+ if containerName in ["value", "list", "dict"]:
150
+ self.__containerTypeName = containerName
151
+ return True
152
+ return False
153
+
154
+ def getContainerTypeName(self):
155
+ return self.__containerTypeName
156
+
157
+ def getValueTypeName(self):
158
+ return self.__valueTypeName
@@ -0,0 +1,89 @@
1
+ ##
2
+ # File: WfDataObject.py
3
+ # Date: 5-April-2010
4
+ #
5
+ # Updates:
6
+ # 1-May-2015 jdw add common output method
7
+ # 7-Sep-2015 jdw add __str__ and __repl__
8
+ #
9
+ ##
10
+ """
11
+ Mixin container the workflow data object.
12
+
13
+ """
14
+
15
+ __docformat__ = "restructuredtext en"
16
+ __author__ = "John Westbrook"
17
+ __email__ = "jwest@rcsb.rutgers.edu"
18
+ __license__ = "Creative Commons Attribution 3.0 Unported"
19
+ __version__ = "V0.01"
20
+
21
+ try:
22
+ import cStringIO as StringIO # type: ignore[import-not-found]
23
+ except ImportError:
24
+ import io as StringIO # noqa: N812
25
+
26
+ from wwpdb.io.locator.DataReference import DataFileReference
27
+
28
+ from wwpdb.utils.wf.DataSelector import DataSelector
29
+ from wwpdb.utils.wf.DataValueContainer import DataValueContainer
30
+
31
+
32
+ class WfDataObject(DataSelector, DataValueContainer, DataFileReference):
33
+ """Top-level container for workflow data object.
34
+
35
+ This container includes some combination of the following:
36
+ - A data file reference (`DataFileReference`)
37
+ - A data value container (`DataValueContainer`)
38
+ - A data selector (`DataSelector`)
39
+
40
+ """
41
+
42
+ # Inherit base __init__
43
+ # def __init__(self):
44
+ # super(WfDataObject, self).__init__()
45
+ # self.__verbose = False
46
+ # sys.stderr.write("WfDataObject.__init_()\n")
47
+
48
+ def printMe(self, ofh):
49
+ if self.getReferenceType() in ["file"]:
50
+ ofh.write("+WfDataObject.printMe() reference type %s\n" % self.getReferenceType())
51
+ ofh.write("+WfDataObject.printMe() version ID %s\n" % self.getVersionId())
52
+ ofh.write("+WfDataObject.printMe() data set ID %s\n" % self.getDepositionDataSetId())
53
+ ofh.write("+WfDataObject.printMe() partition number %s\n" % self.getPartitionNumber())
54
+ ofh.write("+WfDataObject.printMe() content type %s\n" % self.getContentType())
55
+ ofh.write("+WfDataObject.printMe() file format %s\n" % self.getFileFormat())
56
+ ofh.write("+WfDataObject.printMe() storage type %s\n" % self.getStorageType())
57
+ ofh.write("+WfDataObject.printMe() directory path %s\n" % self.getDirPathReference())
58
+ ofh.write("+WfDataObject.printMe() file path %s\n" % self.getFilePathReference())
59
+ if self.getSelectorType() is not None:
60
+ ofh.write("+WfDataObject.printMe() selector type %s\n" % self.getSelectorType())
61
+ ofh.write("+WfDataObject.printMe() select category %s\n" % self.getSelectCategoryName())
62
+ ofh.write("+WfDataObject.printMe() select attributes %r\n" % self.getSelectAttributeList())
63
+ ofh.write("+WfDataObject.printMe() select conditions %r\n" % self.getSelectConditionList())
64
+ elif self.getContainerTypeName() in ["value", "list", "dict"]:
65
+ ofh.write("+WfDataObject.printMe() container type %s\n" % self.getContainerTypeName())
66
+ ofh.write("+WfDataObject.printMe() value type %s\n" % self.getValueTypeName())
67
+ ofh.write("+WfDataObject.printMe() is value set %r\n" % self.isValueSet())
68
+ ofh.write("+WfDataObject.printMe() is value valid %r\n" % self.isValueValid())
69
+ ofh.write("+WfDataObject.printMe() data value %r\n" % self.getValue())
70
+ else:
71
+ ofh.write("+WfDataObject.printMe() undefined data object\n")
72
+
73
+ def __str__(self):
74
+ output = StringIO.StringIO()
75
+ self.printMe(ofh=output)
76
+ contents = output.getvalue()
77
+ output.close()
78
+ return contents
79
+
80
+ def __repr__(self):
81
+ output = StringIO.StringIO()
82
+ self.printMe(ofh=output)
83
+ contents = output.getvalue()
84
+ output.close()
85
+ return contents
86
+
87
+
88
+ if __name__ == "__main__":
89
+ wfd = WfDataObject()
@@ -0,0 +1,5 @@
1
+ __docformat__ = "restructuredtext en"
2
+ __author__ = "Ezra Peisach"
3
+ __email__ = "ezra.peisach@rcsb.org"
4
+ __license__ = "Apache 2.0"
5
+ __version__ = "0.43"
@@ -0,0 +1,237 @@
1
+ ##
2
+ # File: DbApiUtil.py
3
+ # Date: 04-May-2015
4
+ # Updates:
5
+ ##
6
+ """
7
+ Providing general APIs for database access
8
+
9
+ This software was developed as part of the World Wide Protein Data Bank
10
+ Common Deposition and Annotation System Project
11
+
12
+ Copyright (c) 2015 wwPDB
13
+
14
+ This software is provided under a Creative Commons Attribution 3.0 Unported
15
+ License described at http://creativecommons.org/licenses/by/3.0/.
16
+
17
+ """
18
+
19
+ __docformat__ = "restructuredtext en"
20
+ __author__ = "Zukang Feng"
21
+ __email__ = "zfeng@rcsb.rutgers.edu"
22
+ __license__ = "Creative Commons Attribution 3.0 Unported"
23
+ __version__ = "V0.07"
24
+
25
+ import datetime
26
+ import os
27
+ import sys
28
+ import time
29
+
30
+ import MySQLdb
31
+
32
+ #
33
+ from wwpdb.utils.wf.dbapi.DbConnection import DbConnection
34
+
35
+
36
+ class DbApiUtil:
37
+ def __init__(
38
+ self,
39
+ dbServer=None,
40
+ dbHost=None,
41
+ dbName=None,
42
+ dbUser=None,
43
+ dbPw=None,
44
+ dbSocket=None,
45
+ dbPort=None,
46
+ verbose=False,
47
+ log=sys.stderr,
48
+ ):
49
+ """ """
50
+ self.__debug = False
51
+ self.__Nretry = 5
52
+ self.__dbServer = dbServer
53
+ self.__dbHost = dbHost
54
+ self.__dbName = dbName
55
+ self.__dbUser = dbUser
56
+ self.__dbPw = dbPw
57
+ self.__dbSocket = dbSocket
58
+ self.__dbPort = dbPort
59
+ self.__verbose = verbose # pylint: disable=unused-private-member
60
+ self.__lfh = log
61
+ self.__schemaMap = {}
62
+ self.__dbState = 0
63
+
64
+ if self.__debug:
65
+ self.__lfh.write("\n+DbApiUtil.__init__() using socket %r\n" % self.__dbSocket)
66
+ self.__lfh.write("+DbApiUtil.__init__() using socket environment reference %r\n" % os.getenv("SITE_DB_SOCKET", None))
67
+
68
+ self.__myDb = DbConnection(
69
+ dbServer=self.__dbServer,
70
+ dbHost=self.__dbHost,
71
+ dbName=self.__dbName,
72
+ dbUser=self.__dbUser,
73
+ dbPw=self.__dbPw,
74
+ dbPort=self.__dbPort,
75
+ dbSocket=self.__dbSocket,
76
+ )
77
+
78
+ self.__dbcon = self.__myDb.connect()
79
+
80
+ def __reConnect(self):
81
+ """ """
82
+ try:
83
+ self.__myDb.close(self.__dbcon)
84
+ except MySQLdb.Error:
85
+ self.__lfh.write("+DbApiUtil.reConnect() DB connection lost - cannot close\n")
86
+ self.__lfh.write("+DbApiUtil.reConnect() Re-connecting to the database ..\n")
87
+ self.__lfh.write("+DbApiUtil.reConnect() UTC time = %s\n" % datetime.datetime.utcnow()) # noqa: DTZ003
88
+
89
+ for i in range(1, self.__Nretry):
90
+ try:
91
+ self.__dbcon = self.__myDb.connect()
92
+ self.__dbState = 0
93
+ return True
94
+ except MySQLdb.Error:
95
+ self.__lfh.write("+DbApiUtil.reConnect() Cannot get re-connection : trying again\n")
96
+ time.sleep(2 * i)
97
+
98
+ return False
99
+
100
+ def __runSelectSQL(self, query):
101
+ """ """
102
+ rows = ()
103
+ try:
104
+ self.__dbcon.commit()
105
+ curs = self.__dbcon.cursor(MySQLdb.cursors.DictCursor)
106
+ curs.execute(query)
107
+ rows = curs.fetchall()
108
+ except MySQLdb.Error as e:
109
+ self.__dbState = e.args[0]
110
+ self.__lfh.write("Database error %s: %s\n" % (e.args[0], e.args[1]))
111
+
112
+ return rows
113
+
114
+ def __runUpdateSQL(self, query):
115
+ """ """
116
+ try:
117
+ curs = self.__dbcon.cursor()
118
+ curs.execute("set autocommit=0")
119
+ _nrows = curs.execute(query) # noqa: F841
120
+ self.__dbcon.commit()
121
+ curs.execute("set autocommit=1")
122
+ curs.close()
123
+ return "OK"
124
+ except MySQLdb.Error as e:
125
+ self.__dbcon.rollback()
126
+ self.__dbState = e.args[0]
127
+ self.__lfh.write("Database error %s: %s\n" % (e.args[0], e.args[1]))
128
+ #
129
+ return None
130
+
131
+ def setSchemaMap(self, schemaMap):
132
+ """ """
133
+ self.__schemaMap = schemaMap
134
+
135
+ def runSelectSQL(self, sql):
136
+ """method to run a query"""
137
+ for retry in range(1, self.__Nretry):
138
+ ret = self.__runSelectSQL(sql)
139
+ if ret is None:
140
+ if self.__dbState > 0:
141
+ time.sleep(retry * 2)
142
+ if not self.__reConnect():
143
+ return None
144
+ else:
145
+ return None
146
+ #
147
+ else:
148
+ return ret
149
+ #
150
+ #
151
+ return None
152
+
153
+ def runUpdateSQL(self, sql):
154
+ """method to run a query"""
155
+ for retry in range(1, self.__Nretry):
156
+ ret = self.__runUpdateSQL(sql)
157
+ if ret is None:
158
+ if self.__dbState > 0:
159
+ time.sleep(retry * 2)
160
+ if not self.__reConnect():
161
+ return None
162
+ else:
163
+ return None
164
+ #
165
+ else:
166
+ return ret
167
+ #
168
+ #
169
+ return None
170
+
171
+ def runUpdate(self, table=None, where=None, data=None):
172
+ if not table:
173
+ return None
174
+ #
175
+ if (not where) and (not data):
176
+ return None
177
+ #
178
+ rowExists = False
179
+ if where:
180
+ sql = (
181
+ "select * from " # noqa: S608
182
+ + str(table)
183
+ + " where "
184
+ + " and ".join(["%s = '%s'" % (k, v.replace("'", "\\'")) for k, v in where.items()])
185
+ ) # noqa: S608
186
+ rows = self.runSelectSQL(sql)
187
+ if rows and len(rows) > 0:
188
+ rowExists = True
189
+ #
190
+ #
191
+ if rowExists and (not data):
192
+ return "OK"
193
+ #
194
+ if rowExists:
195
+ sql = (
196
+ "update " # noqa: S608
197
+ + str(table)
198
+ + " set "
199
+ + ",".join(["%s = '%s'" % (k, v.replace("'", "\\'")) for k, v in data.items()])
200
+ ) # noqa: S608
201
+ if where:
202
+ sql += " where " + " and ".join(["%s = '%s'" % (k, v.replace("'", "\\'")) for k, v in where.items()])
203
+ #
204
+ else:
205
+ sql = "insert into " + str(table) + " (" + ",".join(["%s" % (k) for k, v in where.items()])
206
+ if data:
207
+ sql += "," + ",".join(["%s" % (k) for k, v in data.items()])
208
+ #
209
+ sql += ") values (" + ",".join(["'%s'" % (v.replace("'", "\\'")) for k, v in where.items()])
210
+ if data:
211
+ sql += "," + ",".join(["'%s'" % (v.replace("'", "\\'")) for k, v in data.items()])
212
+ #
213
+ sql += ")"
214
+ #
215
+ return self.runUpdateSQL(sql)
216
+
217
+ def runUpdateSQLwithKey(self, key=None, parameter=()):
218
+ """ """
219
+ if not key or not self.__schemaMap or (key not in self.__schemaMap):
220
+ return None
221
+ #
222
+ sql = self.__schemaMap[key]
223
+ if parameter:
224
+ sql = self.__schemaMap[key] % parameter
225
+ #
226
+ return self.runUpdateSQL(sql)
227
+
228
+ def selectData(self, key=None, parameter=()):
229
+ """ """
230
+ if key is None or not self.__schemaMap or (key not in self.__schemaMap):
231
+ return None
232
+ #
233
+ sql = self.__schemaMap[key]
234
+ if parameter:
235
+ sql = self.__schemaMap[key] % parameter
236
+ #
237
+ return self.runSelectSQL(sql)