testgres.postgres-configuration 0.1.0__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.
- testgres/postgres_configuration/__init__.py +22 -0
- testgres/postgres_configuration/abstract/v00/configuration.py +435 -0
- testgres/postgres_configuration/core/bugcheck_error.py +219 -0
- testgres/postgres_configuration/core/controller_utils.py +982 -0
- testgres/postgres_configuration/core/data_verificator.py +60 -0
- testgres/postgres_configuration/core/handlers.py +483 -0
- testgres/postgres_configuration/core/helpers.py +95 -0
- testgres/postgres_configuration/core/model.py +296 -0
- testgres/postgres_configuration/core/option/handlers/add/option_handler_to_add__std.py +38 -0
- testgres/postgres_configuration/core/option/handlers/get_value/option_handler_to_get_value__std__simple.py +36 -0
- testgres/postgres_configuration/core/option/handlers/get_value/option_handler_to_get_value__std__union_list.py +36 -0
- testgres/postgres_configuration/core/option/handlers/prepare_get_value/option_handler_to_prepare_get_value__std__bool.py +31 -0
- testgres/postgres_configuration/core/option/handlers/prepare_get_value/option_handler_to_prepare_get_value__std__generic.py +41 -0
- testgres/postgres_configuration/core/option/handlers/prepare_get_value/option_handler_to_prepare_get_value__std__int.py +31 -0
- testgres/postgres_configuration/core/option/handlers/prepare_get_value/option_handler_to_prepare_get_value__std__str.py +31 -0
- testgres/postgres_configuration/core/option/handlers/prepare_get_value/option_handler_to_prepare_get_value__std__unique_str_list.py +46 -0
- testgres/postgres_configuration/core/option/handlers/prepare_set_value/option_handler_to_prepare_set_value__std__bool.py +115 -0
- testgres/postgres_configuration/core/option/handlers/prepare_set_value/option_handler_to_prepare_set_value__std__generic.py +41 -0
- testgres/postgres_configuration/core/option/handlers/prepare_set_value/option_handler_to_prepare_set_value__std__int.py +44 -0
- testgres/postgres_configuration/core/option/handlers/prepare_set_value/option_handler_to_prepare_set_value__std__str.py +37 -0
- testgres/postgres_configuration/core/option/handlers/prepare_set_value/option_handler_to_prepare_set_value__std__unique_str_list.py +63 -0
- testgres/postgres_configuration/core/option/handlers/prepare_set_value_item/option_handler_to_prepare_set_value_item__std__str.py +37 -0
- testgres/postgres_configuration/core/option/handlers/set_value/option_handler_to_set_value__std__simple.py +38 -0
- testgres/postgres_configuration/core/option/handlers/set_value_item/option_handler_to_set_value_item__std__unique.py +38 -0
- testgres/postgres_configuration/core/option/handlers/write/option_handler_to_write__std__bool.py +42 -0
- testgres/postgres_configuration/core/option/handlers/write/option_handler_to_write__std__generic.py +51 -0
- testgres/postgres_configuration/core/option/handlers/write/option_handler_to_write__std__int.py +27 -0
- testgres/postgres_configuration/core/option/handlers/write/option_handler_to_write__std__str.py +36 -0
- testgres/postgres_configuration/core/option/handlers/write/option_handler_to_write__std__unique_str_list.py +37 -0
- testgres/postgres_configuration/core/raise_error.py +365 -0
- testgres/postgres_configuration/core/read_utils.py +308 -0
- testgres/postgres_configuration/core/write_utils.py +112 -0
- testgres/postgres_configuration/implementation/v00/configuration_base.py +4408 -0
- testgres/postgres_configuration/implementation/v00/configuration_std.py +538 -0
- testgres/postgres_configuration/os/abstract/configuration_os_ops.py +98 -0
- testgres/postgres_configuration/os/local/configuration_os_ops.py +154 -0
- testgres_postgres_configuration-0.1.0.dist-info/METADATA +25 -0
- testgres_postgres_configuration-0.1.0.dist-info/RECORD +40 -0
- testgres_postgres_configuration-0.1.0.dist-info/WHEEL +5 -0
- testgres_postgres_configuration-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# //////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
# Postgres Pro. PostgreSQL Configuration Python Library.
|
|
3
|
+
|
|
4
|
+
import datetime
|
|
5
|
+
|
|
6
|
+
# //////////////////////////////////////////////////////////////////////////////
|
|
7
|
+
# RaiseError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RaiseError:
|
|
11
|
+
def MethodIsNotImplemented(classType: type, methodName: str):
|
|
12
|
+
assert type(classType) == type
|
|
13
|
+
assert type(methodName) == str
|
|
14
|
+
assert methodName != ""
|
|
15
|
+
|
|
16
|
+
errMsg = "Method {0}::{1} is not implemented.".format(
|
|
17
|
+
classType.__name__, methodName
|
|
18
|
+
)
|
|
19
|
+
raise NotImplementedError(errMsg)
|
|
20
|
+
|
|
21
|
+
# --------------------------------------------------------------------
|
|
22
|
+
def GetPropertyIsNotImplemented(classType: type, methodName: str):
|
|
23
|
+
assert type(classType) == type
|
|
24
|
+
assert type(methodName) == str
|
|
25
|
+
assert methodName != ""
|
|
26
|
+
|
|
27
|
+
errMsg = "Get property {0}::{1} is not implemented.".format(
|
|
28
|
+
classType.__name__, methodName
|
|
29
|
+
)
|
|
30
|
+
raise NotImplementedError(errMsg)
|
|
31
|
+
|
|
32
|
+
# --------------------------------------------------------------------
|
|
33
|
+
def OptionNameIsNone():
|
|
34
|
+
errMsg = "Option name is None."
|
|
35
|
+
raise Exception(errMsg)
|
|
36
|
+
|
|
37
|
+
# --------------------------------------------------------------------
|
|
38
|
+
def OptionNameHasBadType(nameType: type):
|
|
39
|
+
assert nameType is not None
|
|
40
|
+
assert type(nameType) == type
|
|
41
|
+
|
|
42
|
+
errMsg = "Option name has nad type [{0}]".format(nameType.__name__)
|
|
43
|
+
raise Exception(errMsg)
|
|
44
|
+
|
|
45
|
+
# --------------------------------------------------------------------
|
|
46
|
+
def OptionNameIsEmpty():
|
|
47
|
+
errMsg = "Option name is empty."
|
|
48
|
+
raise Exception(errMsg)
|
|
49
|
+
|
|
50
|
+
# --------------------------------------------------------------------
|
|
51
|
+
def NoneValueIsNotSupported():
|
|
52
|
+
errMsg = "None value is not supported."
|
|
53
|
+
raise Exception(errMsg)
|
|
54
|
+
|
|
55
|
+
# --------------------------------------------------------------------
|
|
56
|
+
def NoneOptionValueItemIsNotSupported(optionName: str):
|
|
57
|
+
assert type(optionName) == str
|
|
58
|
+
assert optionName != ""
|
|
59
|
+
|
|
60
|
+
errMsg = "None value item of option [{0}] is not supported.".format(optionName)
|
|
61
|
+
raise Exception(errMsg)
|
|
62
|
+
|
|
63
|
+
# --------------------------------------------------------------------
|
|
64
|
+
def CommentObjectWasDeleted():
|
|
65
|
+
errMsg = "Comment object was deleted."
|
|
66
|
+
raise Exception(errMsg)
|
|
67
|
+
|
|
68
|
+
# --------------------------------------------------------------------
|
|
69
|
+
def OptionObjectWasDeleted():
|
|
70
|
+
errMsg = "Option object was deleted."
|
|
71
|
+
raise Exception(errMsg)
|
|
72
|
+
|
|
73
|
+
# --------------------------------------------------------------------
|
|
74
|
+
def IncludeObjectWasDeleted():
|
|
75
|
+
errMsg = "Include object was deleted."
|
|
76
|
+
raise Exception(errMsg)
|
|
77
|
+
|
|
78
|
+
# --------------------------------------------------------------------
|
|
79
|
+
def FileLineObjectWasDeleted():
|
|
80
|
+
errMsg = "FileLine object was deleted."
|
|
81
|
+
raise Exception(errMsg)
|
|
82
|
+
|
|
83
|
+
# --------------------------------------------------------------------
|
|
84
|
+
def FileObjectWasDeleted():
|
|
85
|
+
errMsg = "File object was deleted."
|
|
86
|
+
raise Exception(errMsg)
|
|
87
|
+
|
|
88
|
+
# --------------------------------------------------------------------
|
|
89
|
+
def BadOptionValueType(optionName: str, optionValueType: type, expectedType: type):
|
|
90
|
+
assert type(optionName) == str
|
|
91
|
+
assert type(optionValueType) == type
|
|
92
|
+
assert type(expectedType) == type
|
|
93
|
+
|
|
94
|
+
errMsg = "Bad option [{0}] value type [{1}]. Expected type is [{2}].".format(
|
|
95
|
+
optionName, optionValueType.__name__, expectedType.__name__
|
|
96
|
+
)
|
|
97
|
+
raise Exception(errMsg)
|
|
98
|
+
|
|
99
|
+
# --------------------------------------------------------------------
|
|
100
|
+
def CantConvertOptionValue(optionName: str, sourceType: type, targetType: type):
|
|
101
|
+
assert type(optionName) == str
|
|
102
|
+
assert type(sourceType) == type
|
|
103
|
+
assert type(targetType) == type
|
|
104
|
+
|
|
105
|
+
errMsg = (
|
|
106
|
+
"Can't convert option [{0}] value from type [{1}] to type [{2}].".format(
|
|
107
|
+
optionName, sourceType.__name__, targetType.__name__
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
raise Exception(errMsg)
|
|
111
|
+
|
|
112
|
+
# --------------------------------------------------------------------
|
|
113
|
+
def BadOptionValueItemType(
|
|
114
|
+
optionName: str, optionValueItemType: type, expectedType: type
|
|
115
|
+
):
|
|
116
|
+
assert type(optionName) == str
|
|
117
|
+
assert type(optionValueItemType) == type
|
|
118
|
+
assert type(expectedType) == type
|
|
119
|
+
|
|
120
|
+
errMsg = (
|
|
121
|
+
"Bad option [{0}] value item type [{1}]. Expected type is [{2}].".format(
|
|
122
|
+
optionName, optionValueItemType.__name__, expectedType.__name__
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
raise Exception(errMsg)
|
|
126
|
+
|
|
127
|
+
# --------------------------------------------------------------------
|
|
128
|
+
def CommentTextContainsInvalidSymbols():
|
|
129
|
+
errMsg = "Comment text contains invalid symbols."
|
|
130
|
+
raise Exception(errMsg)
|
|
131
|
+
|
|
132
|
+
# --------------------------------------------------------------------
|
|
133
|
+
def FileIsAlreadyRegistered(file_path: str):
|
|
134
|
+
errMsg = "File [{0}] is already registered.".format(file_path)
|
|
135
|
+
raise Exception(errMsg)
|
|
136
|
+
|
|
137
|
+
# --------------------------------------------------------------------
|
|
138
|
+
def OptionIsAlreadyExistInThisFile(filePath: str, optionName: str):
|
|
139
|
+
assert type(filePath) == str
|
|
140
|
+
assert type(optionName) == str
|
|
141
|
+
assert filePath != ""
|
|
142
|
+
assert optionName != ""
|
|
143
|
+
|
|
144
|
+
errMsg = "Option [{0}] already exist in this file [{1}].".format(
|
|
145
|
+
optionName, filePath
|
|
146
|
+
)
|
|
147
|
+
raise Exception(errMsg)
|
|
148
|
+
|
|
149
|
+
# --------------------------------------------------------------------
|
|
150
|
+
def OptionIsAlreadyExistInAnotherFile(filePath: str, optionName: str):
|
|
151
|
+
assert type(filePath) == str
|
|
152
|
+
assert type(optionName) == str
|
|
153
|
+
assert filePath != ""
|
|
154
|
+
assert optionName != ""
|
|
155
|
+
|
|
156
|
+
errMsg = "Option [{0}] already exist in another file [{1}].".format(
|
|
157
|
+
optionName, filePath
|
|
158
|
+
)
|
|
159
|
+
raise Exception(errMsg)
|
|
160
|
+
|
|
161
|
+
# --------------------------------------------------------------------
|
|
162
|
+
def OptionIsAlreadyExistInFile(filePath: str, optionName: str):
|
|
163
|
+
assert type(filePath) == str
|
|
164
|
+
assert type(optionName) == str
|
|
165
|
+
assert filePath != ""
|
|
166
|
+
assert optionName != ""
|
|
167
|
+
|
|
168
|
+
errMsg = "Option [{0}] already exist in the file [{1}].".format(
|
|
169
|
+
optionName, filePath
|
|
170
|
+
)
|
|
171
|
+
raise Exception(errMsg)
|
|
172
|
+
|
|
173
|
+
# --------------------------------------------------------------------
|
|
174
|
+
def OptionValueItemIsAlreadyDefined(filePath: str, optName: str, valueItem: any):
|
|
175
|
+
assert type(filePath) == str
|
|
176
|
+
assert type(optName) == str
|
|
177
|
+
|
|
178
|
+
errMsg = "Another definition of option [{1}] value item [{2}] is found in the file [{0}].".format(
|
|
179
|
+
filePath, optName, valueItem
|
|
180
|
+
)
|
|
181
|
+
raise Exception(errMsg)
|
|
182
|
+
|
|
183
|
+
# --------------------------------------------------------------------
|
|
184
|
+
def OptionValueItemIsAlreadyDefinedInAnotherFile(
|
|
185
|
+
filePath: str, optName: str, valueItem: any
|
|
186
|
+
):
|
|
187
|
+
assert type(filePath) == str
|
|
188
|
+
assert type(optName) == str
|
|
189
|
+
|
|
190
|
+
errMsg = "Definition of option [{1}] value item [{2}] is found in another file [{0}].".format(
|
|
191
|
+
filePath, optName, valueItem
|
|
192
|
+
)
|
|
193
|
+
raise Exception(errMsg)
|
|
194
|
+
|
|
195
|
+
# --------------------------------------------------------------------
|
|
196
|
+
def UnknownFileName(fileName: str):
|
|
197
|
+
assert type(fileName) == str
|
|
198
|
+
|
|
199
|
+
errMsg = "Unknown file name [{0}].".format(fileName)
|
|
200
|
+
raise Exception(errMsg)
|
|
201
|
+
|
|
202
|
+
# --------------------------------------------------------------------
|
|
203
|
+
def MultipleDefOfFileIsFound(fileName: str, count: int):
|
|
204
|
+
assert type(fileName) == str
|
|
205
|
+
assert type(count) == int
|
|
206
|
+
|
|
207
|
+
errMsg = "Multiple definitition of file [{0}] is found - {1}.".format(
|
|
208
|
+
fileName, count
|
|
209
|
+
)
|
|
210
|
+
raise Exception(errMsg)
|
|
211
|
+
|
|
212
|
+
# --------------------------------------------------------------------
|
|
213
|
+
def FilePathIsEmpty():
|
|
214
|
+
errMsg = "File path is empty."
|
|
215
|
+
raise Exception(errMsg)
|
|
216
|
+
|
|
217
|
+
# --------------------------------------------------------------------
|
|
218
|
+
def FileWasModifiedExternally(
|
|
219
|
+
filePath: str,
|
|
220
|
+
ourLastMDate: datetime.datetime,
|
|
221
|
+
curLastMDate: datetime.datetime,
|
|
222
|
+
):
|
|
223
|
+
assert type(filePath) == str
|
|
224
|
+
assert type(ourLastMDate) == datetime.datetime
|
|
225
|
+
assert type(curLastMDate) == datetime.datetime
|
|
226
|
+
|
|
227
|
+
errMsg = "File [{0}] was modified externally. Our timestamp is [{1}]. The current file timestamp is [{2}].".format(
|
|
228
|
+
filePath, ourLastMDate, curLastMDate
|
|
229
|
+
)
|
|
230
|
+
raise Exception(errMsg)
|
|
231
|
+
|
|
232
|
+
# --------------------------------------------------------------------
|
|
233
|
+
def FileLineAlreadyHasComment():
|
|
234
|
+
errMsg = "File line already has a comment."
|
|
235
|
+
raise Exception(errMsg)
|
|
236
|
+
|
|
237
|
+
# --------------------------------------------------------------------
|
|
238
|
+
def FileLineAlreadyHasOption(optionName: str):
|
|
239
|
+
assert type(optionName) == str
|
|
240
|
+
|
|
241
|
+
errMsg = "File line already has the option [{0}].".format(optionName)
|
|
242
|
+
raise Exception(errMsg)
|
|
243
|
+
|
|
244
|
+
# --------------------------------------------------------------------
|
|
245
|
+
def FileLineAlreadyHasIncludeDirective():
|
|
246
|
+
errMsg = "File line already has an include directive."
|
|
247
|
+
|
|
248
|
+
raise Exception(errMsg)
|
|
249
|
+
|
|
250
|
+
# --------------------------------------------------------------------
|
|
251
|
+
def CfgReader__UnexpectedSymbol(lineNum: int, colNum: int, ch: str):
|
|
252
|
+
assert type(lineNum) == int
|
|
253
|
+
assert type(colNum) == int
|
|
254
|
+
assert type(ch) == str
|
|
255
|
+
|
|
256
|
+
errMsg = "Unexpected symbol in line {0}, column {1}: [{2}]".format(
|
|
257
|
+
lineNum, colNum, ch
|
|
258
|
+
)
|
|
259
|
+
raise Exception(errMsg)
|
|
260
|
+
|
|
261
|
+
# --------------------------------------------------------------------
|
|
262
|
+
def CfgReader__IncludeWithoutPath(lineNum: int):
|
|
263
|
+
assert type(lineNum) == int
|
|
264
|
+
assert lineNum >= 0
|
|
265
|
+
|
|
266
|
+
errMsg = "Include directive in line {0} does not have a path.".format(lineNum)
|
|
267
|
+
raise Exception(errMsg)
|
|
268
|
+
|
|
269
|
+
# --------------------------------------------------------------------
|
|
270
|
+
def CfgReader__EndOfIncludePathIsNotFound(lineNum: int):
|
|
271
|
+
assert type(lineNum) == int
|
|
272
|
+
assert lineNum >= 0
|
|
273
|
+
|
|
274
|
+
errMsg = "The end of an include path is not found. Line {0}.".format(lineNum)
|
|
275
|
+
raise Exception(errMsg)
|
|
276
|
+
|
|
277
|
+
# --------------------------------------------------------------------
|
|
278
|
+
def CfgReader__IncompletedEscapeInInclude(lineNum: int):
|
|
279
|
+
assert type(lineNum) == int
|
|
280
|
+
assert lineNum >= 0
|
|
281
|
+
|
|
282
|
+
errMsg = "Escape in an include path is not completed. Line {0}.".format(lineNum)
|
|
283
|
+
raise Exception(errMsg)
|
|
284
|
+
|
|
285
|
+
# --------------------------------------------------------------------
|
|
286
|
+
def CfgReader__UnknownEscapedSymbolInInclude(lineNum: int, colNum: int, ch: str):
|
|
287
|
+
assert type(lineNum) == int
|
|
288
|
+
assert type(colNum) == int
|
|
289
|
+
assert type(ch) == str
|
|
290
|
+
assert lineNum >= 0
|
|
291
|
+
assert colNum >= 0
|
|
292
|
+
assert ch != ""
|
|
293
|
+
|
|
294
|
+
errMsg = "Unknown escape symbol [{2}] in an include path. Line {0}. Column {1}.".format(
|
|
295
|
+
lineNum, colNum, ch
|
|
296
|
+
)
|
|
297
|
+
raise Exception(errMsg)
|
|
298
|
+
|
|
299
|
+
# --------------------------------------------------------------------
|
|
300
|
+
def CfgReader__IncludeHasEmptyPath(lineNum: int):
|
|
301
|
+
assert type(lineNum) == int
|
|
302
|
+
assert lineNum >= 0
|
|
303
|
+
|
|
304
|
+
errMsg = "Include in line {0} has an empty path.".format(lineNum)
|
|
305
|
+
raise Exception(errMsg)
|
|
306
|
+
|
|
307
|
+
# --------------------------------------------------------------------
|
|
308
|
+
def CfgReader__OptionWithoutValue(optionName: str, lineNum: int):
|
|
309
|
+
assert type(lineNum) == int
|
|
310
|
+
assert type(optionName) == str
|
|
311
|
+
assert lineNum >= 0
|
|
312
|
+
assert optionName != ""
|
|
313
|
+
|
|
314
|
+
errMsg = "Option [{0}] in line {1} does not have a value.".format(
|
|
315
|
+
optionName, lineNum
|
|
316
|
+
)
|
|
317
|
+
raise Exception(errMsg)
|
|
318
|
+
|
|
319
|
+
# --------------------------------------------------------------------
|
|
320
|
+
def CfgReader__EndQuotedOptionValueIsNotFound(optionName: str, lineNum: int):
|
|
321
|
+
assert type(lineNum) == int
|
|
322
|
+
assert type(optionName) == str
|
|
323
|
+
assert lineNum >= 0
|
|
324
|
+
assert optionName != ""
|
|
325
|
+
|
|
326
|
+
errMsg = "Value of quoted option [{0}] is not completed. Line {1}.".format(
|
|
327
|
+
optionName, lineNum
|
|
328
|
+
)
|
|
329
|
+
raise Exception(errMsg)
|
|
330
|
+
|
|
331
|
+
# --------------------------------------------------------------------
|
|
332
|
+
def CfgReader__IncompletedEscapeInQuotedOptionValue(optionName: str, lineNum: int):
|
|
333
|
+
assert type(lineNum) == int
|
|
334
|
+
assert type(optionName) == str
|
|
335
|
+
assert lineNum >= 0
|
|
336
|
+
assert optionName != ""
|
|
337
|
+
|
|
338
|
+
errMsg = "Escape in a value of quoted option [{0}] is not completed. Line {1}.".format(
|
|
339
|
+
optionName, lineNum
|
|
340
|
+
)
|
|
341
|
+
raise Exception(errMsg)
|
|
342
|
+
|
|
343
|
+
# --------------------------------------------------------------------
|
|
344
|
+
def CfgReader__UnknownEscapedSymbolInQuotedOptionValue(
|
|
345
|
+
optionName: str, lineNum: int, colNum: int, ch: str
|
|
346
|
+
):
|
|
347
|
+
assert type(lineNum) == int
|
|
348
|
+
assert type(optionName) == str
|
|
349
|
+
assert type(ch) == str
|
|
350
|
+
assert lineNum >= 0
|
|
351
|
+
assert optionName != ""
|
|
352
|
+
assert ch != ""
|
|
353
|
+
|
|
354
|
+
errMsg = "Unknown escape symbol [{3}] in a value of quoted option [{0}]. Line {1}. Column {2}.".format(
|
|
355
|
+
optionName, lineNum, colNum, ch
|
|
356
|
+
)
|
|
357
|
+
raise Exception(errMsg)
|
|
358
|
+
|
|
359
|
+
# --------------------------------------------------------------------
|
|
360
|
+
def BadFormatOfCommaSeparatedList():
|
|
361
|
+
errMsg = "Bad format of comma separated list."
|
|
362
|
+
raise Exception(errMsg)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
# //////////////////////////////////////////////////////////////////////////////
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# //////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
# Postgres Pro. PostgreSQL Configuration Python Library.
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from .raise_error import RaiseError
|
|
7
|
+
|
|
8
|
+
import typing
|
|
9
|
+
|
|
10
|
+
# //////////////////////////////////////////////////////////////////////////////
|
|
11
|
+
# class LineReader
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LineReader:
|
|
15
|
+
C_DEFAULT_TAB_SIZE = 4
|
|
16
|
+
|
|
17
|
+
m_TabSize: int
|
|
18
|
+
|
|
19
|
+
m_LineNum: int
|
|
20
|
+
m_ColNum: int
|
|
21
|
+
m_Next: int
|
|
22
|
+
m_Data: str
|
|
23
|
+
|
|
24
|
+
# --------------------------------------------------------------------
|
|
25
|
+
def __init__(self, tabSize=C_DEFAULT_TAB_SIZE):
|
|
26
|
+
assert type(tabSize) == int
|
|
27
|
+
assert tabSize > 0
|
|
28
|
+
|
|
29
|
+
self.m_TabSize = tabSize
|
|
30
|
+
|
|
31
|
+
self.m_LineNum = 0
|
|
32
|
+
self.m_ColNum = 0
|
|
33
|
+
self.m_Next = 0
|
|
34
|
+
self.m_Data = 0
|
|
35
|
+
|
|
36
|
+
# --------------------------------------------------------------------
|
|
37
|
+
def SetData(self, lineData: str):
|
|
38
|
+
assert type(lineData) == str
|
|
39
|
+
assert type(self.m_LineNum) == int
|
|
40
|
+
assert self.m_LineNum >= 0
|
|
41
|
+
|
|
42
|
+
self.m_Data = lineData
|
|
43
|
+
self.m_LineNum += 1
|
|
44
|
+
self.m_ColNum = 0
|
|
45
|
+
self.m_Next = 0
|
|
46
|
+
|
|
47
|
+
# --------------------------------------------------------------------
|
|
48
|
+
def GetLineNum(self) -> int:
|
|
49
|
+
assert type(self.m_LineNum) == int
|
|
50
|
+
assert self.m_LineNum >= 0
|
|
51
|
+
return self.m_LineNum
|
|
52
|
+
|
|
53
|
+
# --------------------------------------------------------------------
|
|
54
|
+
def GetColNum(self) -> int:
|
|
55
|
+
assert type(self.m_ColNum) == int
|
|
56
|
+
assert self.m_ColNum >= 0
|
|
57
|
+
return self.m_ColNum
|
|
58
|
+
|
|
59
|
+
# --------------------------------------------------------------------
|
|
60
|
+
def GetColOffset(self) -> int:
|
|
61
|
+
assert type(self.m_ColNum) == int
|
|
62
|
+
assert self.m_ColNum > 0
|
|
63
|
+
return self.m_ColNum - 1
|
|
64
|
+
|
|
65
|
+
# --------------------------------------------------------------------
|
|
66
|
+
def StepBack(self):
|
|
67
|
+
assert type(self.m_Next) == int
|
|
68
|
+
assert type(self.m_ColNum) == int
|
|
69
|
+
assert type(self.m_Data) == str
|
|
70
|
+
assert self.m_Next > 0
|
|
71
|
+
assert self.m_Next <= len(self.m_Data)
|
|
72
|
+
assert self.m_ColNum > 0
|
|
73
|
+
|
|
74
|
+
self.m_Next -= 1
|
|
75
|
+
|
|
76
|
+
if self.m_Next == 0:
|
|
77
|
+
assert self.m_ColNum == 1
|
|
78
|
+
self.m_ColNum = 0
|
|
79
|
+
else:
|
|
80
|
+
assert self.m_Next > 0
|
|
81
|
+
stepSize = self.Helper__GetStepSize(self.m_Data[self.m_Next - 1])
|
|
82
|
+
assert self.m_ColNum > stepSize
|
|
83
|
+
self.m_ColNum -= stepSize
|
|
84
|
+
assert self.m_ColNum > 0
|
|
85
|
+
|
|
86
|
+
# --------------------------------------------------------------------
|
|
87
|
+
def ReadSymbol(self) -> typing.Optional[str]:
|
|
88
|
+
assert type(self.m_Next) == int
|
|
89
|
+
assert type(self.m_ColNum) == int
|
|
90
|
+
assert type(self.m_Data) == str
|
|
91
|
+
assert self.m_Next >= 0
|
|
92
|
+
assert self.m_Next <= len(self.m_Data)
|
|
93
|
+
|
|
94
|
+
if self.m_Next == len(self.m_Data):
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
result = self.m_Data[self.m_Next]
|
|
98
|
+
|
|
99
|
+
if self.m_Next == 0:
|
|
100
|
+
self.m_ColNum = 1
|
|
101
|
+
else:
|
|
102
|
+
self.m_ColNum += self.Helper__GetStepSize(self.m_Data[self.m_Next - 1])
|
|
103
|
+
|
|
104
|
+
self.m_Next += 1
|
|
105
|
+
|
|
106
|
+
return result
|
|
107
|
+
|
|
108
|
+
# --------------------------------------------------------------------
|
|
109
|
+
def Helper__GetStepSize(self, ch: str) -> int:
|
|
110
|
+
assert type(ch) == str
|
|
111
|
+
assert ch != ""
|
|
112
|
+
assert type(self.m_TabSize) == int
|
|
113
|
+
assert self.m_TabSize > 0
|
|
114
|
+
|
|
115
|
+
if ch == "\t":
|
|
116
|
+
return self.m_TabSize
|
|
117
|
+
|
|
118
|
+
return 1
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# //////////////////////////////////////////////////////////////////////////////
|
|
122
|
+
# class ReadUtils
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class ReadUtils:
|
|
126
|
+
def IsSpace(ch: str) -> bool:
|
|
127
|
+
assert type(ch) == str
|
|
128
|
+
|
|
129
|
+
if ch == " ":
|
|
130
|
+
return True
|
|
131
|
+
|
|
132
|
+
if ch == "\t":
|
|
133
|
+
return True
|
|
134
|
+
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
# --------------------------------------------------------------------
|
|
138
|
+
def IsEOL(ch: str) -> bool:
|
|
139
|
+
assert type(ch) == str
|
|
140
|
+
|
|
141
|
+
if ch == "\n":
|
|
142
|
+
return True
|
|
143
|
+
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
# --------------------------------------------------------------------
|
|
147
|
+
def IsValidSeqCh1(ch: str) -> bool:
|
|
148
|
+
assert type(ch) == str
|
|
149
|
+
|
|
150
|
+
if ch.isalpha():
|
|
151
|
+
return True
|
|
152
|
+
|
|
153
|
+
if ch in "_":
|
|
154
|
+
return True
|
|
155
|
+
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
# --------------------------------------------------------------------
|
|
159
|
+
def IsValidSeqCh2(ch: str) -> bool:
|
|
160
|
+
assert type(ch) == str
|
|
161
|
+
|
|
162
|
+
if ch.isdigit():
|
|
163
|
+
return True
|
|
164
|
+
|
|
165
|
+
return __class__.IsValidSeqCh1(ch)
|
|
166
|
+
|
|
167
|
+
# --------------------------------------------------------------------
|
|
168
|
+
def Unpack_StrList2(source: str) -> typing.List[str]:
|
|
169
|
+
assert source is not None
|
|
170
|
+
assert type(source) == str
|
|
171
|
+
|
|
172
|
+
C_MODE__NONE = 0
|
|
173
|
+
C_MODE__QSTART = 1
|
|
174
|
+
C_MODE__QEND = 2
|
|
175
|
+
|
|
176
|
+
class tagCtx:
|
|
177
|
+
mode: int
|
|
178
|
+
curValueItem: typing.Optional[str]
|
|
179
|
+
dataLength: int
|
|
180
|
+
result: list[str]
|
|
181
|
+
index: set[str]
|
|
182
|
+
|
|
183
|
+
ctx = tagCtx()
|
|
184
|
+
ctx.mode = C_MODE__NONE
|
|
185
|
+
ctx.curValueItem = None
|
|
186
|
+
ctx.dataLength = 0
|
|
187
|
+
ctx.result = list()
|
|
188
|
+
ctx.index = set()
|
|
189
|
+
|
|
190
|
+
i = 0
|
|
191
|
+
length = len(source)
|
|
192
|
+
|
|
193
|
+
# ----------------------------------------------
|
|
194
|
+
def LOCAL__append_to_curValueItem(ctx: tagCtx, ch: str, isData: bool):
|
|
195
|
+
assert type(ctx) == tagCtx
|
|
196
|
+
assert type(ch) == str
|
|
197
|
+
assert len(ch) == 1
|
|
198
|
+
assert type(isData) == bool
|
|
199
|
+
|
|
200
|
+
if ctx.curValueItem is None:
|
|
201
|
+
ctx.curValueItem = ch
|
|
202
|
+
else:
|
|
203
|
+
assert type(ctx.curValueItem) == str
|
|
204
|
+
ctx.curValueItem += ch
|
|
205
|
+
|
|
206
|
+
if isData:
|
|
207
|
+
ctx.dataLength = len(ctx.curValueItem)
|
|
208
|
+
|
|
209
|
+
return
|
|
210
|
+
|
|
211
|
+
# ----------------------------------------------
|
|
212
|
+
def LOCAL__append_curValueItem_to_result(ctx: tagCtx, isLast: bool):
|
|
213
|
+
assert type(ctx) == tagCtx
|
|
214
|
+
|
|
215
|
+
if ctx.mode == C_MODE__QSTART:
|
|
216
|
+
# quoted item is not completed
|
|
217
|
+
RaiseError.BadFormatOfCommaSeparatedList()
|
|
218
|
+
|
|
219
|
+
if ctx.curValueItem is None:
|
|
220
|
+
if isLast and ctx.mode == C_MODE__NONE:
|
|
221
|
+
return
|
|
222
|
+
s = ""
|
|
223
|
+
elif ctx.mode == C_MODE__QEND:
|
|
224
|
+
s = ctx.curValueItem
|
|
225
|
+
else:
|
|
226
|
+
assert ctx.mode == C_MODE__NONE
|
|
227
|
+
s = ctx.curValueItem[: ctx.dataLength]
|
|
228
|
+
|
|
229
|
+
if s not in ctx.index:
|
|
230
|
+
ctx.index.add(s)
|
|
231
|
+
ctx.result.append(s)
|
|
232
|
+
|
|
233
|
+
ctx.mode = C_MODE__NONE
|
|
234
|
+
ctx.curValueItem = ""
|
|
235
|
+
ctx.dataLength = 0
|
|
236
|
+
return
|
|
237
|
+
|
|
238
|
+
# ----------------------------------------------
|
|
239
|
+
while True:
|
|
240
|
+
assert i >= 0
|
|
241
|
+
assert i <= length
|
|
242
|
+
|
|
243
|
+
if i == length:
|
|
244
|
+
LOCAL__append_curValueItem_to_result(ctx, True)
|
|
245
|
+
return ctx.result # GO HOME!
|
|
246
|
+
|
|
247
|
+
assert i >= 0
|
|
248
|
+
assert i < length
|
|
249
|
+
|
|
250
|
+
ch = source[i]
|
|
251
|
+
|
|
252
|
+
if ch == "," and ctx.mode != C_MODE__QSTART:
|
|
253
|
+
LOCAL__append_curValueItem_to_result(ctx, False)
|
|
254
|
+
i += 1
|
|
255
|
+
continue
|
|
256
|
+
|
|
257
|
+
# space
|
|
258
|
+
if not __class__.IsSpace(ch):
|
|
259
|
+
pass
|
|
260
|
+
else:
|
|
261
|
+
if ctx.mode == C_MODE__QEND:
|
|
262
|
+
i += 1
|
|
263
|
+
continue
|
|
264
|
+
|
|
265
|
+
if ctx.mode == C_MODE__QSTART:
|
|
266
|
+
pass
|
|
267
|
+
elif ctx.curValueItem is None or ctx.curValueItem == "":
|
|
268
|
+
i += 1
|
|
269
|
+
continue
|
|
270
|
+
|
|
271
|
+
# append this RAW space to result
|
|
272
|
+
LOCAL__append_to_curValueItem(ctx, ch, False)
|
|
273
|
+
i += 1
|
|
274
|
+
continue
|
|
275
|
+
|
|
276
|
+
assert not __class__.IsSpace(ch)
|
|
277
|
+
|
|
278
|
+
if ch == '"':
|
|
279
|
+
# quoted item
|
|
280
|
+
if ctx.mode == C_MODE__NONE:
|
|
281
|
+
ctx.mode = C_MODE__QSTART
|
|
282
|
+
i += 1
|
|
283
|
+
continue
|
|
284
|
+
|
|
285
|
+
if ctx.mode == C_MODE__QSTART:
|
|
286
|
+
i += 1
|
|
287
|
+
|
|
288
|
+
if i != length and source[i] == '"':
|
|
289
|
+
LOCAL__append_to_curValueItem(ctx, '"', True)
|
|
290
|
+
i += 1
|
|
291
|
+
continue
|
|
292
|
+
|
|
293
|
+
ctx.mode = C_MODE__QEND
|
|
294
|
+
continue
|
|
295
|
+
|
|
296
|
+
assert ctx.mode == C_MODE__QEND
|
|
297
|
+
RaiseError.BadFormatOfCommaSeparatedList()
|
|
298
|
+
|
|
299
|
+
if ctx.mode == C_MODE__QEND:
|
|
300
|
+
# Data after quoted text
|
|
301
|
+
RaiseError.BadFormatOfCommaSeparatedList()
|
|
302
|
+
|
|
303
|
+
LOCAL__append_to_curValueItem(ctx, ch, True)
|
|
304
|
+
i += 1
|
|
305
|
+
continue
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
# //////////////////////////////////////////////////////////////////////////////
|