pyaccesskit 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.
- pyaccesskit/AGENT_GUIDE.md +455 -0
- pyaccesskit/__init__.py +167 -0
- pyaccesskit/__main__.py +6 -0
- pyaccesskit/_backends/__init__.py +0 -0
- pyaccesskit/_backends/access/__init__.py +1 -0
- pyaccesskit/_backends/access/design.py +415 -0
- pyaccesskit/_backends/dao/__init__.py +1 -0
- pyaccesskit/_backends/dao/profile.py +40 -0
- pyaccesskit/_backends/dao/schema.py +805 -0
- pyaccesskit/_backends/dao/typemap.py +390 -0
- pyaccesskit/_backends/fake/__init__.py +3 -0
- pyaccesskit/_backends/fake/backend.py +680 -0
- pyaccesskit/_backends/protocols.py +339 -0
- pyaccesskit/_com/__init__.py +1 -0
- pyaccesskit/_com/constants.py +394 -0
- pyaccesskit/_com/dispatch.py +50 -0
- pyaccesskit/_com/errors.py +184 -0
- pyaccesskit/_com/gateway.py +199 -0
- pyaccesskit/_com/raw.py +164 -0
- pyaccesskit/_com/runtime.py +39 -0
- pyaccesskit/_com/variants.py +72 -0
- pyaccesskit/_engines/__init__.py +48 -0
- pyaccesskit/_engines/access.py +300 -0
- pyaccesskit/_engines/inproc.py +148 -0
- pyaccesskit/_engines/probe.py +231 -0
- pyaccesskit/_ledger.py +158 -0
- pyaccesskit/_ops/__init__.py +0 -0
- pyaccesskit/_ops/design.py +127 -0
- pyaccesskit/_ops/schema.py +471 -0
- pyaccesskit/_session/__init__.py +1 -0
- pyaccesskit/_session/protocols.py +78 -0
- pyaccesskit/_session/session.py +354 -0
- pyaccesskit/_text/__init__.py +0 -0
- pyaccesskit/_text/codec.py +114 -0
- pyaccesskit/_version.py +3 -0
- pyaccesskit/_win/__init__.py +1 -0
- pyaccesskit/_win/access_process.py +348 -0
- pyaccesskit/_win/console.py +56 -0
- pyaccesskit/_win/inspector.py +53 -0
- pyaccesskit/_win/job.py +65 -0
- pyaccesskit/_win/processes.py +159 -0
- pyaccesskit/_win/watchdog.py +253 -0
- pyaccesskit/cli/__init__.py +10 -0
- pyaccesskit/cli/_output.py +101 -0
- pyaccesskit/cli/agent.py +99 -0
- pyaccesskit/cli/app.py +54 -0
- pyaccesskit/cli/cleanup.py +56 -0
- pyaccesskit/cli/doctor.py +101 -0
- pyaccesskit/cli/inspection.py +223 -0
- pyaccesskit/database.py +296 -0
- pyaccesskit/diagnostics.py +319 -0
- pyaccesskit/enums.py +258 -0
- pyaccesskit/errors.py +407 -0
- pyaccesskit/forms/__init__.py +45 -0
- pyaccesskit/forms/builder.py +295 -0
- pyaccesskit/forms/collection.py +117 -0
- pyaccesskit/forms/controls.py +157 -0
- pyaccesskit/forms/layout.py +300 -0
- pyaccesskit/forms/spec.py +169 -0
- pyaccesskit/forms/vba.py +138 -0
- pyaccesskit/maintenance.py +32 -0
- pyaccesskit/modules.py +101 -0
- pyaccesskit/objects.py +81 -0
- pyaccesskit/options.py +40 -0
- pyaccesskit/properties.py +74 -0
- pyaccesskit/py.typed +0 -0
- pyaccesskit/queries.py +190 -0
- pyaccesskit/relationships.py +143 -0
- pyaccesskit/schema/__init__.py +73 -0
- pyaccesskit/schema/_base.py +55 -0
- pyaccesskit/schema/_reserved_words.py +55 -0
- pyaccesskit/schema/columns.py +609 -0
- pyaccesskit/schema/compat.py +57 -0
- pyaccesskit/schema/expressions.py +162 -0
- pyaccesskit/schema/indexes.py +114 -0
- pyaccesskit/schema/names.py +122 -0
- pyaccesskit/schema/queries.py +192 -0
- pyaccesskit/schema/relationships.py +132 -0
- pyaccesskit/schema/tables.py +178 -0
- pyaccesskit/tables.py +333 -0
- pyaccesskit/units.py +301 -0
- pyaccesskit-0.1.0.dist-info/METADATA +201 -0
- pyaccesskit-0.1.0.dist-info/RECORD +86 -0
- pyaccesskit-0.1.0.dist-info/WHEEL +4 -0
- pyaccesskit-0.1.0.dist-info/entry_points.txt +2 -0
- pyaccesskit-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
"""Access and DAO constants used by PyAccessKit's COM adapters (internal).
|
|
2
|
+
|
|
3
|
+
Generated by ``scripts/gen_constants.py`` from the installed type libraries — do not edit by hand.
|
|
4
|
+
|
|
5
|
+
* Microsoft Access 16.0 Object Library — ``{4AFFC9A0-5F99-101B-AF4E-00AA003F0F07}`` v9.0
|
|
6
|
+
* Microsoft Office 16.0 Access database engine Object Library — ``{4AC9E1DA-5BAD-4AC7-86E3-24F4CDCECA28}`` v12.0
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# ruff: noqa: N815
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from enum import IntEnum
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AcCloseSave(IntEnum):
|
|
16
|
+
"""``AcCloseSave`` (Microsoft Access 16.0 Object Library)."""
|
|
17
|
+
|
|
18
|
+
acSavePrompt = 0
|
|
19
|
+
acSaveYes = 1
|
|
20
|
+
acSaveNo = 2
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AcControlType(IntEnum):
|
|
24
|
+
"""``AcControlType`` (Microsoft Access 16.0 Object Library)."""
|
|
25
|
+
|
|
26
|
+
acLabel = 100
|
|
27
|
+
acRectangle = 101
|
|
28
|
+
acLine = 102
|
|
29
|
+
acImage = 103
|
|
30
|
+
acCommandButton = 104
|
|
31
|
+
acOptionButton = 105
|
|
32
|
+
acCheckBox = 106
|
|
33
|
+
acOptionGroup = 107
|
|
34
|
+
acBoundObjectFrame = 108
|
|
35
|
+
acTextBox = 109
|
|
36
|
+
acListBox = 110
|
|
37
|
+
acComboBox = 111
|
|
38
|
+
acSubform = 112
|
|
39
|
+
acObjectFrame = 114
|
|
40
|
+
acPageBreak = 118
|
|
41
|
+
acCustomControl = 119
|
|
42
|
+
acToggleButton = 122
|
|
43
|
+
acTabCtl = 123
|
|
44
|
+
acPage = 124
|
|
45
|
+
acAttachment = 126
|
|
46
|
+
acEmptyCell = 127
|
|
47
|
+
acWebBrowser = 128
|
|
48
|
+
acNavigationControl = 129
|
|
49
|
+
acNavigationButton = 130
|
|
50
|
+
acChart = 133
|
|
51
|
+
acEdgeBrowser = 134
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class AcDefView(IntEnum):
|
|
55
|
+
"""``AcDefView`` (Microsoft Access 16.0 Object Library)."""
|
|
56
|
+
|
|
57
|
+
acDefViewSingle = 0
|
|
58
|
+
acDefViewContinuous = 1
|
|
59
|
+
acDefViewDatasheet = 2
|
|
60
|
+
acDefViewPivotTable = 3
|
|
61
|
+
acDefViewPivotChart = 4
|
|
62
|
+
acDefViewSplitForm = 5
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class AcFormOpenDataMode(IntEnum):
|
|
66
|
+
"""``AcFormOpenDataMode`` (Microsoft Access 16.0 Object Library)."""
|
|
67
|
+
|
|
68
|
+
acFormPropertySettings = -1
|
|
69
|
+
acFormAdd = 0
|
|
70
|
+
acFormEdit = 1
|
|
71
|
+
acFormReadOnly = 2
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class AcFormView(IntEnum):
|
|
75
|
+
"""``AcFormView`` (Microsoft Access 16.0 Object Library)."""
|
|
76
|
+
|
|
77
|
+
acNormal = 0
|
|
78
|
+
acDesign = 1
|
|
79
|
+
acPreview = 2
|
|
80
|
+
acFormDS = 3
|
|
81
|
+
acFormPivotTable = 4
|
|
82
|
+
acFormPivotChart = 5
|
|
83
|
+
acLayout = 6
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class AcModuleType(IntEnum):
|
|
87
|
+
"""``AcModuleType`` (Microsoft Access 16.0 Object Library)."""
|
|
88
|
+
|
|
89
|
+
acStandardModule = 0
|
|
90
|
+
acClassModule = 1
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class AcNewDatabaseFormat(IntEnum):
|
|
94
|
+
"""``AcNewDatabaseFormat`` (Microsoft Access 16.0 Object Library)."""
|
|
95
|
+
|
|
96
|
+
acNewDatabaseFormatUserDefault = 0
|
|
97
|
+
acNewDatabaseFormatAccess2000 = 9
|
|
98
|
+
acNewDatabaseFormatAccess2002 = 10
|
|
99
|
+
acNewDatabaseFormatAccess2007 = 12
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class AcObjectType(IntEnum):
|
|
103
|
+
"""``AcObjectType`` (Microsoft Access 16.0 Object Library)."""
|
|
104
|
+
|
|
105
|
+
acDefault = -1
|
|
106
|
+
acTable = 0
|
|
107
|
+
acQuery = 1
|
|
108
|
+
acForm = 2
|
|
109
|
+
acReport = 3
|
|
110
|
+
acMacro = 4
|
|
111
|
+
acModule = 5
|
|
112
|
+
acDataAccessPage = 6
|
|
113
|
+
acServerView = 7
|
|
114
|
+
acDiagram = 8
|
|
115
|
+
acStoredProcedure = 9
|
|
116
|
+
acFunction = 10
|
|
117
|
+
acDatabaseProperties = 11
|
|
118
|
+
acTableDataMacro = 12
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class AcQuitOption(IntEnum):
|
|
122
|
+
"""``AcQuitOption`` (Microsoft Access 16.0 Object Library)."""
|
|
123
|
+
|
|
124
|
+
acQuitPrompt = 0
|
|
125
|
+
acQuitSaveAll = 1
|
|
126
|
+
acQuitSaveNone = 2
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class AcSection(IntEnum):
|
|
130
|
+
"""``AcSection`` (Microsoft Access 16.0 Object Library)."""
|
|
131
|
+
|
|
132
|
+
acDetail = 0
|
|
133
|
+
acHeader = 1
|
|
134
|
+
acFooter = 2
|
|
135
|
+
acPageHeader = 3
|
|
136
|
+
acPageFooter = 4
|
|
137
|
+
acGroupLevel1Header = 5
|
|
138
|
+
acGroupLevel1Footer = 6
|
|
139
|
+
acGroupLevel2Header = 7
|
|
140
|
+
acGroupLevel2Footer = 8
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class AcSysCmdAction(IntEnum):
|
|
144
|
+
"""``AcSysCmdAction`` (Microsoft Access 16.0 Object Library)."""
|
|
145
|
+
|
|
146
|
+
acSysCmdInitMeter = 1
|
|
147
|
+
acSysCmdUpdateMeter = 2
|
|
148
|
+
acSysCmdRemoveMeter = 3
|
|
149
|
+
acSysCmdSetStatus = 4
|
|
150
|
+
acSysCmdClearStatus = 5
|
|
151
|
+
acSysCmdRuntime = 6
|
|
152
|
+
acSysCmdAccessVer = 7
|
|
153
|
+
acSysCmdIniFile = 8
|
|
154
|
+
acSysCmdAccessDir = 9
|
|
155
|
+
acSysCmdGetObjectState = 10
|
|
156
|
+
acSysCmdClearHelpTopic = 11
|
|
157
|
+
acSysCmdProfile = 12
|
|
158
|
+
acSysCmdGetWorkgroupFile = 13
|
|
159
|
+
acSysCmdCompile = 603
|
|
160
|
+
acSysCmdGetMsoBuildNumber = 715
|
|
161
|
+
acSysCmdGetFullVersion = 720
|
|
162
|
+
acSysCmdGetVersion = 721
|
|
163
|
+
acSysCmdGetFullBuildNumber = 722
|
|
164
|
+
acSysCmdGetChannelName = 723
|
|
165
|
+
acSysCmdGetBitness = 724
|
|
166
|
+
acSysCmdGetBuildNumber = 725
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class AcView(IntEnum):
|
|
170
|
+
"""``AcView`` (Microsoft Access 16.0 Object Library)."""
|
|
171
|
+
|
|
172
|
+
acViewNormal = 0
|
|
173
|
+
acViewDesign = 1
|
|
174
|
+
acViewPreview = 2
|
|
175
|
+
acViewPivotTable = 3
|
|
176
|
+
acViewPivotChart = 4
|
|
177
|
+
acViewReport = 5
|
|
178
|
+
acViewLayout = 6
|
|
179
|
+
acViewSql = 7
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class AcWindowMode(IntEnum):
|
|
183
|
+
"""``AcWindowMode`` (Microsoft Access 16.0 Object Library)."""
|
|
184
|
+
|
|
185
|
+
acWindowNormal = 0
|
|
186
|
+
acHidden = 1
|
|
187
|
+
acIcon = 2
|
|
188
|
+
acDialog = 3
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class DataTypeEnum(IntEnum):
|
|
192
|
+
"""``DataTypeEnum`` (Microsoft Office 16.0 Access database engine Object Library)."""
|
|
193
|
+
|
|
194
|
+
dbBoolean = 1
|
|
195
|
+
dbByte = 2
|
|
196
|
+
dbInteger = 3
|
|
197
|
+
dbLong = 4
|
|
198
|
+
dbCurrency = 5
|
|
199
|
+
dbSingle = 6
|
|
200
|
+
dbDouble = 7
|
|
201
|
+
dbDate = 8
|
|
202
|
+
dbBinary = 9
|
|
203
|
+
dbText = 10
|
|
204
|
+
dbLongBinary = 11
|
|
205
|
+
dbMemo = 12
|
|
206
|
+
dbGUID = 15
|
|
207
|
+
dbBigInt = 16
|
|
208
|
+
dbVarBinary = 17
|
|
209
|
+
dbChar = 18
|
|
210
|
+
dbNumeric = 19
|
|
211
|
+
dbDecimal = 20
|
|
212
|
+
dbFloat = 21
|
|
213
|
+
dbTime = 22
|
|
214
|
+
dbTimeStamp = 23
|
|
215
|
+
dbDateTimeExtended = 26
|
|
216
|
+
dbAttachment = 101
|
|
217
|
+
dbComplexByte = 102
|
|
218
|
+
dbComplexInteger = 103
|
|
219
|
+
dbComplexLong = 104
|
|
220
|
+
dbComplexSingle = 105
|
|
221
|
+
dbComplexDouble = 106
|
|
222
|
+
dbComplexGUID = 107
|
|
223
|
+
dbComplexDecimal = 108
|
|
224
|
+
dbComplexText = 109
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class DatabaseTypeEnum(IntEnum):
|
|
228
|
+
"""``DatabaseTypeEnum`` (Microsoft Office 16.0 Access database engine Object Library)."""
|
|
229
|
+
|
|
230
|
+
dbVersion10 = 1
|
|
231
|
+
dbEncrypt = 2
|
|
232
|
+
dbDecrypt = 4
|
|
233
|
+
dbVersion11 = 8
|
|
234
|
+
dbVersion20 = 16
|
|
235
|
+
dbVersion30 = 32
|
|
236
|
+
dbVersion40 = 64
|
|
237
|
+
dbVersion120 = 128
|
|
238
|
+
dbVersion140 = 256
|
|
239
|
+
dbVersion150 = 512
|
|
240
|
+
dbVersion167 = 1024
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class FieldAttributeEnum(IntEnum):
|
|
244
|
+
"""``FieldAttributeEnum`` (Microsoft Office 16.0 Access database engine Object Library)."""
|
|
245
|
+
|
|
246
|
+
dbFixedField = 1
|
|
247
|
+
dbVariableField = 2
|
|
248
|
+
dbAutoIncrField = 16
|
|
249
|
+
dbUpdatableField = 32
|
|
250
|
+
dbSystemField = 8192
|
|
251
|
+
dbHyperlinkField = 32768
|
|
252
|
+
dbDescending = 1
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class QueryDefTypeEnum(IntEnum):
|
|
256
|
+
"""``QueryDefTypeEnum`` (Microsoft Office 16.0 Access database engine Object Library)."""
|
|
257
|
+
|
|
258
|
+
dbQSelect = 0
|
|
259
|
+
dbQProcedure = 224
|
|
260
|
+
dbQAction = 240
|
|
261
|
+
dbQCrosstab = 16
|
|
262
|
+
dbQDelete = 32
|
|
263
|
+
dbQUpdate = 48
|
|
264
|
+
dbQAppend = 64
|
|
265
|
+
dbQMakeTable = 80
|
|
266
|
+
dbQDDL = 96
|
|
267
|
+
dbQSQLPassThrough = 112
|
|
268
|
+
dbQSetOperation = 128
|
|
269
|
+
dbQSPTBulk = 144
|
|
270
|
+
dbQCompound = 160
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class RecordsetOptionEnum(IntEnum):
|
|
274
|
+
"""``RecordsetOptionEnum`` (Microsoft Office 16.0 Access database engine Object Library)."""
|
|
275
|
+
|
|
276
|
+
dbDenyWrite = 1
|
|
277
|
+
dbDenyRead = 2
|
|
278
|
+
dbReadOnly = 4
|
|
279
|
+
dbAppendOnly = 8
|
|
280
|
+
dbInconsistent = 16
|
|
281
|
+
dbConsistent = 32
|
|
282
|
+
dbSQLPassThrough = 64
|
|
283
|
+
dbFailOnError = 128
|
|
284
|
+
dbForwardOnly = 256
|
|
285
|
+
dbSeeChanges = 512
|
|
286
|
+
dbRunAsync = 1024
|
|
287
|
+
dbExecDirect = 2048
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
class RecordsetTypeEnum(IntEnum):
|
|
291
|
+
"""``RecordsetTypeEnum`` (Microsoft Office 16.0 Access database engine Object Library)."""
|
|
292
|
+
|
|
293
|
+
dbOpenTable = 1
|
|
294
|
+
dbOpenDynaset = 2
|
|
295
|
+
dbOpenSnapshot = 4
|
|
296
|
+
dbOpenForwardOnly = 8
|
|
297
|
+
dbOpenDynamic = 16
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class RelationAttributeEnum(IntEnum):
|
|
301
|
+
"""``RelationAttributeEnum`` (Microsoft Office 16.0 Access database engine Object Library)."""
|
|
302
|
+
|
|
303
|
+
dbRelationUnique = 1
|
|
304
|
+
dbRelationDontEnforce = 2
|
|
305
|
+
dbRelationInherited = 4
|
|
306
|
+
dbRelationUpdateCascade = 256
|
|
307
|
+
dbRelationDeleteCascade = 4096
|
|
308
|
+
dbRelationLeft = 16777216
|
|
309
|
+
dbRelationRight = 33554432
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class TableDefAttributeEnum(IntEnum):
|
|
313
|
+
"""``TableDefAttributeEnum`` (Microsoft Office 16.0 Access database engine Object Library)."""
|
|
314
|
+
|
|
315
|
+
dbAttachExclusive = 65536
|
|
316
|
+
dbAttachSavePWD = 131072
|
|
317
|
+
dbSystemObject = -2147483646
|
|
318
|
+
dbAttachedTable = 1073741824
|
|
319
|
+
dbAttachedODBC = 536870912
|
|
320
|
+
dbHiddenObject = 1
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
# LanguageConstants (Microsoft Office 16.0 Access database engine Object Library)
|
|
324
|
+
dbLangArabic = ';LANGID=0x0401;CP=1256;COUNTRY=0'
|
|
325
|
+
dbLangCzech = ';LANGID=0x0405;CP=1250;COUNTRY=0'
|
|
326
|
+
dbLangDutch = ';LANGID=0x0413;CP=1252;COUNTRY=0'
|
|
327
|
+
dbLangGeneral = ';LANGID=0x0409;CP=1252;COUNTRY=0'
|
|
328
|
+
dbLangGreek = ';LANGID=0x0408;CP=1253;COUNTRY=0'
|
|
329
|
+
dbLangHebrew = ';LANGID=0x040D;CP=1255;COUNTRY=0'
|
|
330
|
+
dbLangHungarian = ';LANGID=0x040E;CP=1250;COUNTRY=0'
|
|
331
|
+
dbLangIcelandic = ';LANGID=0x040F;CP=1252;COUNTRY=0'
|
|
332
|
+
dbLangNordic = ';LANGID=0x041D;CP=1252;COUNTRY=0'
|
|
333
|
+
dbLangNorwDan = ';LANGID=0x0406;CP=1252;COUNTRY=0'
|
|
334
|
+
dbLangPolish = ';LANGID=0x0415;CP=1250;COUNTRY=0'
|
|
335
|
+
dbLangCyrillic = ';LANGID=0x0419;CP=1251;COUNTRY=0'
|
|
336
|
+
dbLangSpanish = ';LANGID=0x040A;CP=1252;COUNTRY=0'
|
|
337
|
+
dbLangSwedFin = ';LANGID=0x041D;CP=1252;COUNTRY=0'
|
|
338
|
+
dbLangTurkish = ';LANGID=0x041F;CP=1254;COUNTRY=0'
|
|
339
|
+
dbLangJapanese = ';LANGID=0x0411;CP=932;COUNTRY=0'
|
|
340
|
+
dbLangChineseSimplified = ';LANGID=0x0804;CP=936;COUNTRY=0'
|
|
341
|
+
dbLangChineseTraditional = ';LANGID=0x0404;CP=950;COUNTRY=0'
|
|
342
|
+
dbLangKorean = ';LANGID=0x0412;CP=949;COUNTRY=0'
|
|
343
|
+
dbLangThai = ';LANGID=0x041E;CP=874;COUNTRY=0'
|
|
344
|
+
dbLangSlovenian = ';LANGID=0x0424;CP=1250;COUNTRY=0'
|
|
345
|
+
dbLangJapaneseRadicalStrokeCount = ';LANGID=0x00040411;CP=65001;COUNTRY=0'
|
|
346
|
+
dbLangHindi = ';LANGID=0x00000439;CP=65001;COUNTRY=0'
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
class MsoAutomationSecurity(IntEnum):
|
|
350
|
+
"""``Application.AutomationSecurity`` values (Office core type library)."""
|
|
351
|
+
|
|
352
|
+
msoAutomationSecurityLow = 1
|
|
353
|
+
msoAutomationSecurityByUI = 2
|
|
354
|
+
msoAutomationSecurityForceDisable = 3
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
class AdoSchema(IntEnum):
|
|
358
|
+
"""ADO ``SchemaEnum`` values used for column introspection."""
|
|
359
|
+
|
|
360
|
+
adSchemaColumns = 4
|
|
361
|
+
adSchemaIndexes = 12
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
class FormScrollBars(IntEnum):
|
|
365
|
+
"""Values of the Access ``Form.ScrollBars`` property."""
|
|
366
|
+
|
|
367
|
+
neither = 0
|
|
368
|
+
horizontal = 1
|
|
369
|
+
vertical = 2
|
|
370
|
+
both = 3
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
class TextFormat(IntEnum):
|
|
374
|
+
"""Values of the Access ``TextFormat`` field property (Long Text)."""
|
|
375
|
+
|
|
376
|
+
plain_text = 0
|
|
377
|
+
rich_text = 1
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
# Well-known Win32/COM HRESULTs (as signed 32-bit integers, the way pywin32 reports them).
|
|
381
|
+
def _hresult(value: int) -> int:
|
|
382
|
+
return value - 0x1_0000_0000 if value & 0x8000_0000 else value
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
DISP_E_EXCEPTION = _hresult(0x80020009)
|
|
386
|
+
REGDB_E_CLASSNOTREG = _hresult(0x80040154)
|
|
387
|
+
CO_E_SERVER_EXEC_FAILURE = _hresult(0x80080005)
|
|
388
|
+
RPC_E_CALL_REJECTED = _hresult(0x80010001)
|
|
389
|
+
RPC_E_SERVERCALL_RETRYLATER = _hresult(0x8001010A)
|
|
390
|
+
RPC_E_DISCONNECTED = _hresult(0x80010108)
|
|
391
|
+
RPC_E_SERVERFAULT = _hresult(0x80010105)
|
|
392
|
+
RPC_S_SERVER_UNAVAILABLE = _hresult(0x800706BA)
|
|
393
|
+
RPC_S_CALL_FAILED = _hresult(0x800706BE)
|
|
394
|
+
CO_E_OBJNOTCONNECTED = _hresult(0x800401FD)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# pyright: basic, reportArgumentType=false, reportAttributeAccessIssue=false, reportIndexIssue=false
|
|
2
|
+
# (the types-pywin32 stubs are stricter than the COM runtime, e.g. unkOuter=None is valid)
|
|
3
|
+
"""Creation of COM objects — always late-bound, never attached to a running instance.
|
|
4
|
+
|
|
5
|
+
* ``win32com.client.Dispatch(progid)`` first calls ``GetActiveObject`` and would *attach to a user's running
|
|
6
|
+
Access* (ADR 0001, F1). PyAccessKit always uses ``CoCreateInstanceEx`` instead.
|
|
7
|
+
* ``Dispatch``/``DispatchEx`` return early- or late-bound wrappers depending on the machine's makepy cache.
|
|
8
|
+
``win32com.client.dynamic.Dispatch`` keeps the whole object graph late-bound, so behaviour is identical
|
|
9
|
+
on every machine.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import pythoncom
|
|
17
|
+
import pywintypes
|
|
18
|
+
from win32com.client import dynamic
|
|
19
|
+
|
|
20
|
+
from pyaccesskit._com.runtime import ensure_com_initialized
|
|
21
|
+
|
|
22
|
+
__all__ = ["create_inproc", "create_local_server", "wrap"]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def wrap(obj: Any) -> Any:
|
|
26
|
+
"""Wrap a raw ``PyIDispatch``/``PyIUnknown`` in a late-bound dispatch object."""
|
|
27
|
+
if isinstance(obj, pythoncom.TypeIIDs[pythoncom.IID_IDispatch]):
|
|
28
|
+
return dynamic.Dispatch(obj)
|
|
29
|
+
if isinstance(obj, pythoncom.TypeIIDs[pythoncom.IID_IUnknown]):
|
|
30
|
+
return dynamic.Dispatch(obj.QueryInterface(pythoncom.IID_IDispatch))
|
|
31
|
+
return obj
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def create_local_server(progid: str) -> Any:
|
|
35
|
+
"""Start a **new** instance of an out-of-process COM server (e.g. ``Access.Application``)."""
|
|
36
|
+
ensure_com_initialized()
|
|
37
|
+
clsid = pywintypes.IID(progid)
|
|
38
|
+
unknown = pythoncom.CoCreateInstanceEx(
|
|
39
|
+
clsid, None, pythoncom.CLSCTX_LOCAL_SERVER, None, (pythoncom.IID_IDispatch,)
|
|
40
|
+
)[0]
|
|
41
|
+
return dynamic.Dispatch(unknown)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def create_inproc(progid: str) -> Any:
|
|
45
|
+
"""Load an in-process COM server (e.g. ``DAO.DBEngine.120``) into this Python process."""
|
|
46
|
+
ensure_com_initialized()
|
|
47
|
+
unknown = pythoncom.CoCreateInstance(
|
|
48
|
+
progid, None, pythoncom.CLSCTX_INPROC_SERVER, pythoncom.IID_IDispatch
|
|
49
|
+
)
|
|
50
|
+
return dynamic.Dispatch(unknown)
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# pyright: basic
|
|
2
|
+
"""Translate ``pywintypes.com_error`` into PyAccessKit exceptions.
|
|
3
|
+
|
|
4
|
+
Access and DAO report errors as ``DISP_E_EXCEPTION`` whose EXCEPINFO carries ``scode = 0x800A0000 | number``
|
|
5
|
+
(FACILITY_CONTROL) — verified for every number below in spike S9. DAO errors have a ``DAO.<Collection>``
|
|
6
|
+
source; Access application errors have no source but a filled description.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import traceback
|
|
12
|
+
from collections.abc import Sequence
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from pyaccesskit._com import constants as c
|
|
18
|
+
from pyaccesskit.enums import ObjectKind
|
|
19
|
+
from pyaccesskit.errors import (
|
|
20
|
+
AccessProcessDiedError,
|
|
21
|
+
ComError,
|
|
22
|
+
DaoError,
|
|
23
|
+
DatabaseExistsError,
|
|
24
|
+
DatabaseLockedError,
|
|
25
|
+
DatabaseNotFoundError,
|
|
26
|
+
EngineUnavailableError,
|
|
27
|
+
ErrorDetails,
|
|
28
|
+
IntegrityViolationError,
|
|
29
|
+
InvalidPasswordError,
|
|
30
|
+
MissingParameterError,
|
|
31
|
+
ObjectExistsError,
|
|
32
|
+
ObjectInUseError,
|
|
33
|
+
ObjectNotFoundError,
|
|
34
|
+
PyAccessKitError,
|
|
35
|
+
ReadOnlyError,
|
|
36
|
+
RelationshipError,
|
|
37
|
+
SchemaError,
|
|
38
|
+
SqlSyntaxError,
|
|
39
|
+
UnrecognizedFormatError,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
__all__ = ["OpContext", "details_from", "translate"]
|
|
43
|
+
|
|
44
|
+
FACILITY_CONTROL = 0x0A
|
|
45
|
+
|
|
46
|
+
NOT_FOUND = frozenset({3011, 3078, 3265, 2102, 2103, 2450, 2451, 2465, 7874})
|
|
47
|
+
EXISTS = frozenset({3010, 3012, 3191, 3284, 3367, 3380})
|
|
48
|
+
DB_EXISTS = frozenset({3204, 7865})
|
|
49
|
+
DB_NOT_FOUND = frozenset({3024, 3044})
|
|
50
|
+
LOCKED = frozenset({3006, 3045, 3050, 3356, 3734, 7866})
|
|
51
|
+
IN_USE = frozenset({3008, 3009, 3211, 3262})
|
|
52
|
+
PASSWORD = frozenset({3031})
|
|
53
|
+
FORMAT = frozenset({3049, 3343})
|
|
54
|
+
SQL_SYNTAX = frozenset(
|
|
55
|
+
{3075, 3122, 3129, 3131, 3134, 3141, 3144, 3145, 3292, 3293, 3306, 3319, 3346}
|
|
56
|
+
)
|
|
57
|
+
MISSING_PARAMETER = frozenset({3061})
|
|
58
|
+
RELATIONSHIP = frozenset({3366, 3368, 3609})
|
|
59
|
+
INTEGRITY = frozenset({3022, 3200, 3201})
|
|
60
|
+
SCHEMA = frozenset({3125, 3259, 3280, 3283, 3303, 3375})
|
|
61
|
+
READ_ONLY = frozenset({3027})
|
|
62
|
+
PROCESS_DIED = frozenset(
|
|
63
|
+
{
|
|
64
|
+
c.RPC_E_DISCONNECTED,
|
|
65
|
+
c.RPC_S_SERVER_UNAVAILABLE,
|
|
66
|
+
c.RPC_S_CALL_FAILED,
|
|
67
|
+
c.RPC_E_SERVERFAULT,
|
|
68
|
+
c.CO_E_OBJNOTCONNECTED,
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
UNAVAILABLE = frozenset(
|
|
72
|
+
{c.REGDB_E_CLASSNOTREG, c.CO_E_SERVER_EXEC_FAILURE, -2147221005}
|
|
73
|
+
) # + CO_E_CLASSSTRING
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class OpContext:
|
|
78
|
+
"""What PyAccessKit was doing when a COM call failed (used to build precise messages)."""
|
|
79
|
+
|
|
80
|
+
action: str
|
|
81
|
+
kind: ObjectKind | None = None
|
|
82
|
+
name: str | None = None
|
|
83
|
+
path: Path | None = None
|
|
84
|
+
sql: str | None = None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _signed(value: int | None) -> int | None:
|
|
88
|
+
if value is None:
|
|
89
|
+
return None
|
|
90
|
+
value &= 0xFFFFFFFF
|
|
91
|
+
return value - 0x1_0000_0000 if value & 0x8000_0000 else value
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def details_from(exc: Any, dao_errors: Sequence[DaoError] = ()) -> ErrorDetails:
|
|
95
|
+
"""Extract :class:`ErrorDetails` from a ``pywintypes.com_error`` (or any exception with its ``args``)."""
|
|
96
|
+
args = tuple(getattr(exc, "args", ()))
|
|
97
|
+
hresult = _signed(args[0]) if args and isinstance(args[0], int) else None
|
|
98
|
+
message = args[1] if len(args) > 1 and isinstance(args[1], str) else None
|
|
99
|
+
excepinfo = args[2] if len(args) > 2 and isinstance(args[2], tuple) else None
|
|
100
|
+
source = description = None
|
|
101
|
+
scode = None
|
|
102
|
+
if excepinfo and len(excepinfo) >= 6:
|
|
103
|
+
source = excepinfo[1] or None
|
|
104
|
+
description = excepinfo[2] or None
|
|
105
|
+
scode = _signed(excepinfo[5]) if isinstance(excepinfo[5], int) else None
|
|
106
|
+
number = None
|
|
107
|
+
if scode is not None and ((scode >> 16) & 0x1FFF) == FACILITY_CONTROL:
|
|
108
|
+
number = scode & 0xFFFF
|
|
109
|
+
if description is None and scode is None:
|
|
110
|
+
description = message
|
|
111
|
+
matching: tuple[DaoError, ...] = ()
|
|
112
|
+
if dao_errors and number is not None and dao_errors[-1].number == number:
|
|
113
|
+
matching = tuple(
|
|
114
|
+
dao_errors
|
|
115
|
+
) # DBEngine.Errors keeps stale entries; only trust a matching one
|
|
116
|
+
return ErrorDetails(
|
|
117
|
+
hresult=hresult,
|
|
118
|
+
scode=scode,
|
|
119
|
+
number=number,
|
|
120
|
+
source=source,
|
|
121
|
+
description=description.strip() if description else None,
|
|
122
|
+
dao_errors=matching,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _message(ctx: OpContext, details: ErrorDetails) -> str:
|
|
127
|
+
summary = details.summary() or "unknown COM error"
|
|
128
|
+
return f"cannot {ctx.action}: {summary}"
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def translate(
|
|
132
|
+
exc: BaseException, ctx: OpContext, dao_errors: Sequence[DaoError] = ()
|
|
133
|
+
) -> PyAccessKitError:
|
|
134
|
+
"""Map a COM error to the most specific :mod:`pyaccesskit.errors` exception.
|
|
135
|
+
|
|
136
|
+
The COM-holding locals of the original traceback are cleared (the traceback itself is kept for
|
|
137
|
+
debugging), so an exception kept alive by the caller cannot keep an Access process alive.
|
|
138
|
+
"""
|
|
139
|
+
if exc.__traceback__ is not None:
|
|
140
|
+
traceback.clear_frames(exc.__traceback__)
|
|
141
|
+
details = details_from(exc, dao_errors)
|
|
142
|
+
number = details.number
|
|
143
|
+
message = _message(ctx, details)
|
|
144
|
+
common = {"operation": ctx.action, "details": details}
|
|
145
|
+
|
|
146
|
+
if number is not None:
|
|
147
|
+
if number in NOT_FOUND:
|
|
148
|
+
return ObjectNotFoundError(message, kind=ctx.kind, name=ctx.name, **common)
|
|
149
|
+
if number in EXISTS:
|
|
150
|
+
return ObjectExistsError(message, kind=ctx.kind, name=ctx.name, **common)
|
|
151
|
+
if number in DB_EXISTS:
|
|
152
|
+
return DatabaseExistsError(message, path=ctx.path, **common)
|
|
153
|
+
if number in DB_NOT_FOUND:
|
|
154
|
+
return DatabaseNotFoundError(message, path=ctx.path, **common)
|
|
155
|
+
if number in LOCKED:
|
|
156
|
+
return DatabaseLockedError(message, path=ctx.path, **common)
|
|
157
|
+
if number in IN_USE:
|
|
158
|
+
return ObjectInUseError(message, kind=ctx.kind, name=ctx.name, **common)
|
|
159
|
+
if number in PASSWORD:
|
|
160
|
+
return InvalidPasswordError(message, path=ctx.path, **common)
|
|
161
|
+
if number in FORMAT:
|
|
162
|
+
return UnrecognizedFormatError(message, path=ctx.path, **common)
|
|
163
|
+
if number in SQL_SYNTAX:
|
|
164
|
+
return SqlSyntaxError(message, sql=ctx.sql, **common)
|
|
165
|
+
if number in MISSING_PARAMETER:
|
|
166
|
+
return MissingParameterError(message, sql=ctx.sql, **common)
|
|
167
|
+
if number in RELATIONSHIP:
|
|
168
|
+
return RelationshipError(message, **common)
|
|
169
|
+
if number in INTEGRITY:
|
|
170
|
+
return IntegrityViolationError(message, **common)
|
|
171
|
+
if number in SCHEMA:
|
|
172
|
+
return SchemaError(message, **common)
|
|
173
|
+
if number in READ_ONLY:
|
|
174
|
+
return ReadOnlyError(message, **common)
|
|
175
|
+
|
|
176
|
+
for code in (details.scode, details.hresult):
|
|
177
|
+
if code in PROCESS_DIED:
|
|
178
|
+
return AccessProcessDiedError(
|
|
179
|
+
f"cannot {ctx.action}: the Microsoft Access process stopped responding or exited",
|
|
180
|
+
**common,
|
|
181
|
+
)
|
|
182
|
+
if code in UNAVAILABLE:
|
|
183
|
+
return EngineUnavailableError(message, **common)
|
|
184
|
+
return ComError(message, **common)
|