python-msilib 0.2.0__cp313-cp313-win32.whl → 0.4.0__cp313-cp313-win32.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.
Potentially problematic release.
This version of python-msilib might be problematic. Click here for more details.
- msilib/__init__.py +259 -144
- msilib/_msi.c +25 -51
- msilib/_msi.cp313-win32.pyd +0 -0
- msilib/include/_msi.h +26 -24
- msilib/include/pythoncapi_compat.h +40 -1
- msilib/schema.py +5 -0
- msilib/sequence.py +5 -0
- msilib/text.py +5 -1
- {python_msilib-0.2.0.dist-info → python_msilib-0.4.0.dist-info}/METADATA +2 -1
- python_msilib-0.4.0.dist-info/RECORD +13 -0
- python_msilib-0.2.0.dist-info/RECORD +0 -13
- {python_msilib-0.2.0.dist-info → python_msilib-0.4.0.dist-info}/WHEEL +0 -0
- {python_msilib-0.2.0.dist-info → python_msilib-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {python_msilib-0.2.0.dist-info → python_msilib-0.4.0.dist-info}/top_level.txt +0 -0
msilib/__init__.py
CHANGED
|
@@ -1,17 +1,139 @@
|
|
|
1
|
+
"""Read and write Microsoft Installer files."""
|
|
2
|
+
|
|
1
3
|
# Copyright (C) 2005 Martin v. Löwis
|
|
2
4
|
# Licensed to PSF under a Contributor Agreement.
|
|
3
|
-
|
|
5
|
+
import contextlib
|
|
4
6
|
import fnmatch
|
|
5
7
|
import os
|
|
8
|
+
import platform
|
|
6
9
|
import re
|
|
7
10
|
import string
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
from tempfile import mkstemp
|
|
12
|
+
|
|
13
|
+
from msilib._msi import (
|
|
14
|
+
MSICOLINFO_NAMES,
|
|
15
|
+
MSICOLINFO_TYPES,
|
|
16
|
+
MSIDBOPEN_CREATE,
|
|
17
|
+
MSIDBOPEN_CREATEDIRECT,
|
|
18
|
+
MSIDBOPEN_DIRECT,
|
|
19
|
+
MSIDBOPEN_PATCHFILE,
|
|
20
|
+
MSIDBOPEN_READONLY,
|
|
21
|
+
MSIDBOPEN_TRANSACT,
|
|
22
|
+
MSIMODIFY_ASSIGN,
|
|
23
|
+
MSIMODIFY_DELETE,
|
|
24
|
+
MSIMODIFY_INSERT,
|
|
25
|
+
MSIMODIFY_INSERT_TEMPORARY,
|
|
26
|
+
MSIMODIFY_MERGE,
|
|
27
|
+
MSIMODIFY_REFRESH,
|
|
28
|
+
MSIMODIFY_REPLACE,
|
|
29
|
+
MSIMODIFY_SEEK,
|
|
30
|
+
MSIMODIFY_UPDATE,
|
|
31
|
+
MSIMODIFY_VALIDATE,
|
|
32
|
+
MSIMODIFY_VALIDATE_DELETE,
|
|
33
|
+
MSIMODIFY_VALIDATE_FIELD,
|
|
34
|
+
MSIMODIFY_VALIDATE_NEW,
|
|
35
|
+
PID_APPNAME,
|
|
36
|
+
PID_AUTHOR,
|
|
37
|
+
PID_CHARCOUNT,
|
|
38
|
+
PID_CODEPAGE,
|
|
39
|
+
PID_COMMENTS,
|
|
40
|
+
PID_CREATE_DTM,
|
|
41
|
+
PID_KEYWORDS,
|
|
42
|
+
PID_LASTAUTHOR,
|
|
43
|
+
PID_LASTPRINTED,
|
|
44
|
+
PID_LASTSAVE_DTM,
|
|
45
|
+
PID_PAGECOUNT,
|
|
46
|
+
PID_REVNUMBER,
|
|
47
|
+
PID_SECURITY,
|
|
48
|
+
PID_SUBJECT,
|
|
49
|
+
PID_TEMPLATE,
|
|
50
|
+
PID_TITLE,
|
|
51
|
+
PID_WORDCOUNT,
|
|
52
|
+
CreateRecord,
|
|
53
|
+
FCICreate,
|
|
54
|
+
MSIError,
|
|
55
|
+
OpenDatabase,
|
|
56
|
+
UuidCreate,
|
|
57
|
+
)
|
|
11
58
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
59
|
+
__version__ = "0.4.0"
|
|
60
|
+
|
|
61
|
+
__all__ = [
|
|
62
|
+
"CAB",
|
|
63
|
+
"MSICOLINFO_NAMES",
|
|
64
|
+
"MSICOLINFO_TYPES",
|
|
65
|
+
"MSIDBOPEN_CREATE",
|
|
66
|
+
"MSIDBOPEN_CREATEDIRECT",
|
|
67
|
+
"MSIDBOPEN_DIRECT",
|
|
68
|
+
"MSIDBOPEN_PATCHFILE",
|
|
69
|
+
"MSIDBOPEN_READONLY",
|
|
70
|
+
"MSIDBOPEN_TRANSACT",
|
|
71
|
+
"MSIMODIFY_ASSIGN",
|
|
72
|
+
"MSIMODIFY_DELETE",
|
|
73
|
+
"MSIMODIFY_INSERT",
|
|
74
|
+
"MSIMODIFY_INSERT_TEMPORARY",
|
|
75
|
+
"MSIMODIFY_MERGE",
|
|
76
|
+
"MSIMODIFY_REFRESH",
|
|
77
|
+
"MSIMODIFY_REPLACE",
|
|
78
|
+
"MSIMODIFY_SEEK",
|
|
79
|
+
"MSIMODIFY_UPDATE",
|
|
80
|
+
"MSIMODIFY_VALIDATE",
|
|
81
|
+
"MSIMODIFY_VALIDATE_DELETE",
|
|
82
|
+
"MSIMODIFY_VALIDATE_FIELD",
|
|
83
|
+
"MSIMODIFY_VALIDATE_NEW",
|
|
84
|
+
"PID_APPNAME",
|
|
85
|
+
"PID_AUTHOR",
|
|
86
|
+
"PID_CHARCOUNT",
|
|
87
|
+
"PID_CODEPAGE",
|
|
88
|
+
"PID_COMMENTS",
|
|
89
|
+
"PID_CREATE_DTM",
|
|
90
|
+
"PID_KEYWORDS",
|
|
91
|
+
"PID_LASTAUTHOR",
|
|
92
|
+
"PID_LASTPRINTED",
|
|
93
|
+
"PID_LASTSAVE_DTM",
|
|
94
|
+
"PID_PAGECOUNT",
|
|
95
|
+
"PID_REVNUMBER",
|
|
96
|
+
"PID_SECURITY",
|
|
97
|
+
"PID_SUBJECT",
|
|
98
|
+
"PID_TEMPLATE",
|
|
99
|
+
"PID_TITLE",
|
|
100
|
+
"PID_WORDCOUNT",
|
|
101
|
+
"Binary",
|
|
102
|
+
"Control",
|
|
103
|
+
"CreateRecord",
|
|
104
|
+
"Dialog",
|
|
105
|
+
"Directory",
|
|
106
|
+
"FCICreate",
|
|
107
|
+
"Feature",
|
|
108
|
+
"MSIError",
|
|
109
|
+
"OpenDatabase",
|
|
110
|
+
"RadioButtonGroup",
|
|
111
|
+
"Table",
|
|
112
|
+
"UuidCreate",
|
|
113
|
+
"add_data",
|
|
114
|
+
"add_stream",
|
|
115
|
+
"add_tables",
|
|
116
|
+
"change_sequence",
|
|
117
|
+
"datasizemask",
|
|
118
|
+
"gen_uuid",
|
|
119
|
+
"init_database",
|
|
120
|
+
"knownbits",
|
|
121
|
+
"make_id",
|
|
122
|
+
"type_binary",
|
|
123
|
+
"type_key",
|
|
124
|
+
"type_localizable",
|
|
125
|
+
"type_long",
|
|
126
|
+
"type_nullable",
|
|
127
|
+
"type_short",
|
|
128
|
+
"type_string",
|
|
129
|
+
"type_valid",
|
|
130
|
+
"typemask",
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# Should work in windows, but also in mingw, cygwin, ...
|
|
135
|
+
AMD64 = platform.machine() in ("x64", "x86_64", "AMD64")
|
|
136
|
+
ARM64 = platform.machine() in ("aarch64", "arm64", "ARM64")
|
|
15
137
|
|
|
16
138
|
# Partially taken from Wine
|
|
17
139
|
datasizemask = 0x00FF
|
|
@@ -38,30 +160,27 @@ knownbits = (
|
|
|
38
160
|
|
|
39
161
|
|
|
40
162
|
class Table:
|
|
41
|
-
def __init__(self, name):
|
|
163
|
+
def __init__(self, name) -> None:
|
|
42
164
|
self.name = name
|
|
43
165
|
self.fields = []
|
|
44
166
|
|
|
45
|
-
def add_field(self, index, name, type):
|
|
167
|
+
def add_field(self, index, name, type) -> None:
|
|
46
168
|
self.fields.append((index, name, type))
|
|
47
169
|
|
|
48
|
-
def sql(self):
|
|
170
|
+
def sql(self) -> str:
|
|
49
171
|
fields = []
|
|
50
172
|
keys = []
|
|
51
173
|
self.fields.sort()
|
|
52
174
|
fields = [None] * len(self.fields)
|
|
53
|
-
for index, name,
|
|
54
|
-
index
|
|
55
|
-
unk =
|
|
175
|
+
for index, name, ftype in self.fields:
|
|
176
|
+
idx = index - 1
|
|
177
|
+
unk = ftype & ~knownbits
|
|
56
178
|
if unk:
|
|
57
|
-
print("
|
|
58
|
-
size =
|
|
59
|
-
dtype =
|
|
179
|
+
print(f"{self.name}.{name} unknown bits {unk:x}")
|
|
180
|
+
size = ftype & datasizemask
|
|
181
|
+
dtype = ftype & typemask
|
|
60
182
|
if dtype == type_string:
|
|
61
|
-
if size
|
|
62
|
-
tname = "CHAR(%d)" % size
|
|
63
|
-
else:
|
|
64
|
-
tname = "CHAR"
|
|
183
|
+
tname = f"CHAR({size})" if size else "CHAR"
|
|
65
184
|
elif dtype == type_short:
|
|
66
185
|
assert size == 2
|
|
67
186
|
tname = "SHORT"
|
|
@@ -73,25 +192,18 @@ class Table:
|
|
|
73
192
|
tname = "OBJECT"
|
|
74
193
|
else:
|
|
75
194
|
tname = "unknown"
|
|
76
|
-
print("
|
|
77
|
-
if
|
|
78
|
-
|
|
79
|
-
else:
|
|
80
|
-
flags = " NOT NULL"
|
|
81
|
-
if type & type_localizable:
|
|
195
|
+
print(f"{self.name}.{name} unknown integer type {size}")
|
|
196
|
+
flags = "" if ftype & type_nullable else " NOT NULL"
|
|
197
|
+
if ftype & type_localizable:
|
|
82
198
|
flags += " LOCALIZABLE"
|
|
83
|
-
fields[
|
|
84
|
-
if
|
|
85
|
-
keys.append("
|
|
199
|
+
fields[idx] = f"`{name}` {tname}{flags}"
|
|
200
|
+
if ftype & type_key:
|
|
201
|
+
keys.append(f"`{name}`")
|
|
86
202
|
fields = ", ".join(fields)
|
|
87
203
|
keys = ", ".join(keys)
|
|
88
|
-
return "CREATE TABLE
|
|
89
|
-
self.name,
|
|
90
|
-
fields,
|
|
91
|
-
keys,
|
|
92
|
-
)
|
|
204
|
+
return f"CREATE TABLE {self.name} ({fields} PRIMARY KEY {keys})"
|
|
93
205
|
|
|
94
|
-
def create(self, db):
|
|
206
|
+
def create(self, db) -> None:
|
|
95
207
|
v = db.OpenView(self.sql())
|
|
96
208
|
v.Execute(None)
|
|
97
209
|
v.Close()
|
|
@@ -101,8 +213,10 @@ class _Unspecified:
|
|
|
101
213
|
pass
|
|
102
214
|
|
|
103
215
|
|
|
104
|
-
def change_sequence(
|
|
105
|
-
|
|
216
|
+
def change_sequence(
|
|
217
|
+
seq, action, seqno=_Unspecified, cond=_Unspecified
|
|
218
|
+
) -> None:
|
|
219
|
+
"""Change the sequence number of an action in a sequence list."""
|
|
106
220
|
for i in range(len(seq)):
|
|
107
221
|
if seq[i][0] == action:
|
|
108
222
|
if cond is _Unspecified:
|
|
@@ -111,11 +225,12 @@ def change_sequence(seq, action, seqno=_Unspecified, cond=_Unspecified):
|
|
|
111
225
|
seqno = seq[i][2]
|
|
112
226
|
seq[i] = (action, cond, seqno)
|
|
113
227
|
return
|
|
114
|
-
|
|
228
|
+
msg = "Action not found in sequence"
|
|
229
|
+
raise ValueError(msg)
|
|
115
230
|
|
|
116
231
|
|
|
117
|
-
def add_data(db, table, values):
|
|
118
|
-
v = db.OpenView("SELECT * FROM
|
|
232
|
+
def add_data(db, table, values) -> None:
|
|
233
|
+
v = db.OpenView(f"SELECT * FROM `{table}`")
|
|
119
234
|
count = v.GetColumnInfo(MSICOLINFO_NAMES).GetFieldCount()
|
|
120
235
|
r = CreateRecord(count)
|
|
121
236
|
for value in values:
|
|
@@ -131,24 +246,20 @@ def add_data(db, table, values):
|
|
|
131
246
|
elif isinstance(field, Binary):
|
|
132
247
|
r.SetStream(i + 1, field.name)
|
|
133
248
|
else:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
)
|
|
249
|
+
msg = f"Unsupported type {field.__class__.__name__}"
|
|
250
|
+
raise TypeError(msg)
|
|
137
251
|
try:
|
|
138
252
|
v.Modify(MSIMODIFY_INSERT, r)
|
|
139
|
-
except Exception:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
)
|
|
253
|
+
except Exception: # noqa: BLE001
|
|
254
|
+
msg = f"Could not insert {values!r} into {table}"
|
|
255
|
+
raise MSIError(msg) from None
|
|
143
256
|
|
|
144
257
|
r.ClearData()
|
|
145
258
|
v.Close()
|
|
146
259
|
|
|
147
260
|
|
|
148
|
-
def add_stream(db, name, path):
|
|
149
|
-
v = db.OpenView(
|
|
150
|
-
"INSERT INTO _Streams (Name, Data) VALUES ('%s', ?)" % name
|
|
151
|
-
)
|
|
261
|
+
def add_stream(db, name, path) -> None:
|
|
262
|
+
v = db.OpenView(f"INSERT INTO _Streams (Name, Data) VALUES ('{name}', ?)")
|
|
152
263
|
r = CreateRecord(1)
|
|
153
264
|
r.SetStream(1, path)
|
|
154
265
|
v.Execute(r)
|
|
@@ -158,10 +269,8 @@ def add_stream(db, name, path):
|
|
|
158
269
|
def init_database(
|
|
159
270
|
name, schema, ProductName, ProductCode, ProductVersion, Manufacturer
|
|
160
271
|
):
|
|
161
|
-
|
|
272
|
+
with contextlib.suppress(OSError):
|
|
162
273
|
os.unlink(name)
|
|
163
|
-
except OSError:
|
|
164
|
-
pass
|
|
165
274
|
ProductCode = ProductCode.upper()
|
|
166
275
|
# Create the database
|
|
167
276
|
db = OpenDatabase(name, MSIDBOPEN_CREATE)
|
|
@@ -169,14 +278,17 @@ def init_database(
|
|
|
169
278
|
for t in schema.tables:
|
|
170
279
|
t.create(db)
|
|
171
280
|
# Fill the validation table
|
|
172
|
-
add_data(db, "_Validation", schema._Validation_records)
|
|
281
|
+
add_data(db, "_Validation", schema._Validation_records) # noqa: SLF001
|
|
173
282
|
# Initialize the summary information, allowing at most 20 properties
|
|
174
283
|
si = db.GetSummaryInformation(20)
|
|
175
284
|
si.SetProperty(PID_TITLE, "Installation Database")
|
|
176
285
|
si.SetProperty(PID_SUBJECT, ProductName)
|
|
177
286
|
si.SetProperty(PID_AUTHOR, Manufacturer)
|
|
287
|
+
# https://learn.microsoft.com/en-us/windows/win32/msi/template-summary
|
|
178
288
|
if AMD64:
|
|
179
289
|
si.SetProperty(PID_TEMPLATE, "x64;1033")
|
|
290
|
+
elif ARM64:
|
|
291
|
+
si.SetProperty(PID_TEMPLATE, "Arm64;1033")
|
|
180
292
|
else:
|
|
181
293
|
si.SetProperty(PID_TEMPLATE, "Intel;1033")
|
|
182
294
|
si.SetProperty(PID_REVNUMBER, gen_uuid())
|
|
@@ -202,53 +314,52 @@ def init_database(
|
|
|
202
314
|
return db
|
|
203
315
|
|
|
204
316
|
|
|
205
|
-
def add_tables(db, module):
|
|
317
|
+
def add_tables(db, module) -> None:
|
|
206
318
|
for table in module.tables:
|
|
207
319
|
add_data(db, table, getattr(module, table))
|
|
208
320
|
|
|
209
321
|
|
|
210
|
-
def make_id(str):
|
|
322
|
+
def make_id(value: str) -> str:
|
|
211
323
|
identifier_chars = string.ascii_letters + string.digits + "._"
|
|
212
|
-
|
|
213
|
-
if
|
|
214
|
-
|
|
215
|
-
assert re.match("^[A-Za-z_][A-Za-z0-9_.]*$",
|
|
216
|
-
return
|
|
324
|
+
value = "".join([c if c in identifier_chars else "_" for c in value])
|
|
325
|
+
if value[0] in (string.digits + "."):
|
|
326
|
+
value = "_" + value
|
|
327
|
+
assert re.match("^[A-Za-z_][A-Za-z0-9_.]*$", value), "FILE" + value
|
|
328
|
+
return value
|
|
217
329
|
|
|
218
330
|
|
|
219
|
-
def gen_uuid():
|
|
331
|
+
def gen_uuid() -> str:
|
|
220
332
|
return "{" + UuidCreate().upper() + "}"
|
|
221
333
|
|
|
222
334
|
|
|
223
335
|
class CAB:
|
|
224
|
-
def __init__(self, name):
|
|
336
|
+
def __init__(self, name) -> None:
|
|
225
337
|
self.name = name
|
|
226
338
|
self.files = []
|
|
227
339
|
self.filenames = set()
|
|
228
340
|
self.index = 0
|
|
229
341
|
|
|
230
|
-
def gen_id(self, file):
|
|
342
|
+
def gen_id(self, file) -> str:
|
|
231
343
|
logical = _logical = make_id(file)
|
|
232
344
|
pos = 1
|
|
233
345
|
while logical in self.filenames:
|
|
234
|
-
logical = "
|
|
346
|
+
logical = f"{_logical}.{pos}"
|
|
235
347
|
pos += 1
|
|
236
348
|
self.filenames.add(logical)
|
|
237
349
|
return logical
|
|
238
350
|
|
|
239
|
-
def append(self, full, file, logical):
|
|
351
|
+
def append(self, full, file, logical) -> tuple[int, str]:
|
|
240
352
|
if os.path.isdir(full):
|
|
241
|
-
return
|
|
353
|
+
return None
|
|
242
354
|
if not logical:
|
|
243
355
|
logical = self.gen_id(file)
|
|
244
356
|
self.index += 1
|
|
245
357
|
self.files.append((full, logical))
|
|
246
358
|
return self.index, logical
|
|
247
359
|
|
|
248
|
-
def commit(self, db):
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
filename = mktemp()
|
|
360
|
+
def commit(self, db) -> None:
|
|
361
|
+
fd, filename = mkstemp()
|
|
362
|
+
os.close(fd)
|
|
252
363
|
FCICreate(filename, self.files)
|
|
253
364
|
add_data(
|
|
254
365
|
db, "Media", [(1, self.index, None, "#" + self.name, None, None)]
|
|
@@ -271,20 +382,22 @@ class Directory:
|
|
|
271
382
|
_logical,
|
|
272
383
|
default,
|
|
273
384
|
componentflags=None,
|
|
274
|
-
):
|
|
275
|
-
"""Create a new directory in the Directory table. There is a current
|
|
276
|
-
at each point in time for the directory, which is either
|
|
277
|
-
through start_component, or implicitly when files
|
|
278
|
-
time. Files are added into the current
|
|
279
|
-
To create a directory, a base
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
385
|
+
) -> None:
|
|
386
|
+
"""Create a new directory in the Directory table. There is a current
|
|
387
|
+
component at each point in time for the directory, which is either
|
|
388
|
+
explicitly created through start_component, or implicitly when files
|
|
389
|
+
are added for the first time. Files are added into the current
|
|
390
|
+
component, and into the cab file. To create a directory, a base
|
|
391
|
+
directory object needs to be specified (can be None), the path to the
|
|
392
|
+
physical directory, and a logical directory name. Default specifies the
|
|
393
|
+
DefaultDir slot in the directory table. componentflags specifies the
|
|
394
|
+
default flags that new components get.
|
|
395
|
+
"""
|
|
283
396
|
index = 1
|
|
284
397
|
_logical = make_id(_logical)
|
|
285
398
|
logical = _logical
|
|
286
399
|
while logical in _directories:
|
|
287
|
-
logical = "
|
|
400
|
+
logical = f"{_logical}{index}"
|
|
288
401
|
index += 1
|
|
289
402
|
_directories.add(logical)
|
|
290
403
|
self.db = db
|
|
@@ -307,23 +420,22 @@ class Directory:
|
|
|
307
420
|
|
|
308
421
|
def start_component(
|
|
309
422
|
self, component=None, feature=None, flags=None, keyfile=None, uuid=None
|
|
310
|
-
):
|
|
311
|
-
"""Add an entry to the Component table, and make this component the
|
|
312
|
-
directory. If no component name is given, the
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
table.
|
|
423
|
+
) -> None:
|
|
424
|
+
"""Add an entry to the Component table, and make this component the
|
|
425
|
+
current for this directory. If no component name is given, the
|
|
426
|
+
directory name is used. If no feature is given, the current feature is
|
|
427
|
+
used. If no flags are given, the directory's default flags are used. If
|
|
428
|
+
no keyfile is given, the KeyPath is left null in the Component table.
|
|
429
|
+
"""
|
|
316
430
|
if flags is None:
|
|
317
431
|
flags = self.componentflags
|
|
318
|
-
if uuid is None
|
|
319
|
-
uuid = gen_uuid()
|
|
320
|
-
else:
|
|
321
|
-
uuid = uuid.upper()
|
|
432
|
+
uuid = gen_uuid() if uuid is None else uuid.upper()
|
|
322
433
|
if component is None:
|
|
323
434
|
component = self.logical
|
|
324
435
|
self.component = component
|
|
325
|
-
|
|
326
|
-
|
|
436
|
+
# https://learn.microsoft.com/pt-br/windows/win32/msi/component-table
|
|
437
|
+
if AMD64 or ARM64:
|
|
438
|
+
flags |= 256 # msidbComponentAttributes64bit
|
|
327
439
|
if keyfile:
|
|
328
440
|
keyid = self.cab.gen_id(keyfile)
|
|
329
441
|
self.keyfiles[keyfile] = keyid
|
|
@@ -338,10 +450,10 @@ class Directory:
|
|
|
338
450
|
feature = current_feature
|
|
339
451
|
add_data(self.db, "FeatureComponents", [(feature.id, component)])
|
|
340
452
|
|
|
341
|
-
def make_short(self, file):
|
|
453
|
+
def make_short(self, file: str) -> str:
|
|
342
454
|
oldfile = file
|
|
343
455
|
file = file.replace("+", "_")
|
|
344
|
-
file = "".join(c for c in file if not
|
|
456
|
+
file = "".join(c for c in file if c not in r' "/\[]:;=,')
|
|
345
457
|
parts = file.split(".")
|
|
346
458
|
if len(parts) > 1:
|
|
347
459
|
prefix = "".join(parts[:-1]).upper()
|
|
@@ -358,10 +470,7 @@ class Directory:
|
|
|
358
470
|
and file == oldfile
|
|
359
471
|
and (not suffix or len(suffix) <= 3)
|
|
360
472
|
):
|
|
361
|
-
if suffix
|
|
362
|
-
file = prefix + "." + suffix
|
|
363
|
-
else:
|
|
364
|
-
file = prefix
|
|
473
|
+
file = f"{prefix}.{suffix}" if suffix else prefix
|
|
365
474
|
else:
|
|
366
475
|
file = None
|
|
367
476
|
if file is None or file in self.short_names:
|
|
@@ -371,9 +480,9 @@ class Directory:
|
|
|
371
480
|
pos = 1
|
|
372
481
|
while 1:
|
|
373
482
|
if suffix:
|
|
374
|
-
file = "
|
|
483
|
+
file = f"{prefix}~{pos}.{suffix}"
|
|
375
484
|
else:
|
|
376
|
-
file = "
|
|
485
|
+
file = f"{prefix}~{pos}"
|
|
377
486
|
if file not in self.short_names:
|
|
378
487
|
break
|
|
379
488
|
pos += 1
|
|
@@ -381,17 +490,24 @@ class Directory:
|
|
|
381
490
|
if pos in (10, 100, 1000):
|
|
382
491
|
prefix = prefix[:-1]
|
|
383
492
|
self.short_names.add(file)
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
) # restrictions on short names
|
|
493
|
+
# restrictions on short names
|
|
494
|
+
assert not re.search(r'[\?|><:/*"+,;=\[\]]', file)
|
|
387
495
|
return file
|
|
388
496
|
|
|
389
|
-
def add_file(
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
language
|
|
497
|
+
def add_file(
|
|
498
|
+
self,
|
|
499
|
+
file: str,
|
|
500
|
+
src: str | None = None,
|
|
501
|
+
version: str | None = None,
|
|
502
|
+
language: str | None = None,
|
|
503
|
+
) -> str:
|
|
504
|
+
"""Add a file to the current component of the directory, starting a new
|
|
505
|
+
one if there is no current component. By default, the file name in the
|
|
506
|
+
source and the file table will be identical. If the src file is
|
|
507
|
+
specified, it is interpreted relative to the current directory.
|
|
508
|
+
Optionally, a version and a language can be specified for the entry in
|
|
509
|
+
the File table.
|
|
510
|
+
"""
|
|
395
511
|
if not self.component:
|
|
396
512
|
self.start_component(self.logical, current_feature, 0)
|
|
397
513
|
if not src:
|
|
@@ -399,18 +515,14 @@ class Directory:
|
|
|
399
515
|
src = file
|
|
400
516
|
file = os.path.basename(file)
|
|
401
517
|
absolute = os.path.join(self.absolute, src)
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if file in self.keyfiles:
|
|
406
|
-
logical = self.keyfiles[file]
|
|
407
|
-
else:
|
|
408
|
-
logical = None
|
|
518
|
+
# restrictions on long names
|
|
519
|
+
assert not re.search(r'[\?|><:/*]"', file)
|
|
520
|
+
logical = self.keyfiles.get(file, None)
|
|
409
521
|
sequence, logical = self.cab.append(absolute, file, logical)
|
|
410
522
|
assert logical not in self.ids
|
|
411
523
|
self.ids.add(logical)
|
|
412
524
|
short = self.make_short(file)
|
|
413
|
-
full = "
|
|
525
|
+
full = f"{short}|{file}"
|
|
414
526
|
filesize = os.stat(absolute).st_size
|
|
415
527
|
# constants.msidbFileAttributesVital
|
|
416
528
|
# Compressed omitted, since it is the database default
|
|
@@ -450,14 +562,14 @@ class Directory:
|
|
|
450
562
|
(
|
|
451
563
|
logical + "c",
|
|
452
564
|
self.component,
|
|
453
|
-
"
|
|
565
|
+
f"{short}C|{file}c",
|
|
454
566
|
self.logical,
|
|
455
567
|
2,
|
|
456
568
|
),
|
|
457
569
|
(
|
|
458
570
|
logical + "o",
|
|
459
571
|
self.component,
|
|
460
|
-
"
|
|
572
|
+
f"{short}O|{file}o",
|
|
461
573
|
self.logical,
|
|
462
574
|
2,
|
|
463
575
|
),
|
|
@@ -465,9 +577,10 @@ class Directory:
|
|
|
465
577
|
)
|
|
466
578
|
return logical
|
|
467
579
|
|
|
468
|
-
def glob(self, pattern, exclude=None):
|
|
580
|
+
def glob(self, pattern: str, exclude=None) -> list[str]:
|
|
469
581
|
"""Add a list of files to the current component as specified in the
|
|
470
|
-
glob pattern. Individual files can be excluded in the exclude list.
|
|
582
|
+
glob pattern. Individual files can be excluded in the exclude list.
|
|
583
|
+
"""
|
|
471
584
|
try:
|
|
472
585
|
files = os.listdir(self.absolute)
|
|
473
586
|
except OSError:
|
|
@@ -481,8 +594,8 @@ class Directory:
|
|
|
481
594
|
self.add_file(f)
|
|
482
595
|
return files
|
|
483
596
|
|
|
484
|
-
def remove_pyc(self):
|
|
485
|
-
"Remove .pyc files on uninstall"
|
|
597
|
+
def remove_pyc(self) -> None:
|
|
598
|
+
"""Remove .pyc files on uninstall."""
|
|
486
599
|
add_data(
|
|
487
600
|
self.db,
|
|
488
601
|
"RemoveFile",
|
|
@@ -491,11 +604,11 @@ class Directory:
|
|
|
491
604
|
|
|
492
605
|
|
|
493
606
|
class Binary:
|
|
494
|
-
def __init__(self, fname):
|
|
607
|
+
def __init__(self, fname) -> None:
|
|
495
608
|
self.name = fname
|
|
496
609
|
|
|
497
|
-
def __repr__(self):
|
|
498
|
-
return 'msilib.Binary(os.path.join(dirname,"
|
|
610
|
+
def __repr__(self) -> str:
|
|
611
|
+
return f'msilib.Binary(os.path.join(dirname,"{self.name}"))'
|
|
499
612
|
|
|
500
613
|
|
|
501
614
|
class Feature:
|
|
@@ -510,7 +623,7 @@ class Feature:
|
|
|
510
623
|
parent=None,
|
|
511
624
|
directory=None,
|
|
512
625
|
attributes=0,
|
|
513
|
-
):
|
|
626
|
+
) -> None:
|
|
514
627
|
self.id = id
|
|
515
628
|
if parent:
|
|
516
629
|
parent = parent.id
|
|
@@ -520,31 +633,31 @@ class Feature:
|
|
|
520
633
|
[(id, parent, title, desc, display, level, directory, attributes)],
|
|
521
634
|
)
|
|
522
635
|
|
|
523
|
-
def set_current(self):
|
|
636
|
+
def set_current(self) -> None:
|
|
524
637
|
global current_feature
|
|
525
638
|
current_feature = self
|
|
526
639
|
|
|
527
640
|
|
|
528
641
|
class Control:
|
|
529
|
-
def __init__(self, dlg, name):
|
|
642
|
+
def __init__(self, dlg, name) -> None:
|
|
530
643
|
self.dlg = dlg
|
|
531
644
|
self.name = name
|
|
532
645
|
|
|
533
|
-
def event(self, event, argument, condition="1", ordering=None):
|
|
646
|
+
def event(self, event, argument, condition="1", ordering=None) -> None:
|
|
534
647
|
add_data(
|
|
535
648
|
self.dlg.db,
|
|
536
649
|
"ControlEvent",
|
|
537
650
|
[(self.dlg.name, self.name, event, argument, condition, ordering)],
|
|
538
651
|
)
|
|
539
652
|
|
|
540
|
-
def mapping(self, event, attribute):
|
|
653
|
+
def mapping(self, event, attribute) -> None:
|
|
541
654
|
add_data(
|
|
542
655
|
self.dlg.db,
|
|
543
656
|
"EventMapping",
|
|
544
657
|
[(self.dlg.name, self.name, event, attribute)],
|
|
545
658
|
)
|
|
546
659
|
|
|
547
|
-
def condition(self, action, condition):
|
|
660
|
+
def condition(self, action, condition) -> None:
|
|
548
661
|
add_data(
|
|
549
662
|
self.dlg.db,
|
|
550
663
|
"ControlCondition",
|
|
@@ -553,13 +666,13 @@ class Control:
|
|
|
553
666
|
|
|
554
667
|
|
|
555
668
|
class RadioButtonGroup(Control):
|
|
556
|
-
def __init__(self, dlg, name, property):
|
|
669
|
+
def __init__(self, dlg, name, property) -> None:
|
|
557
670
|
self.dlg = dlg
|
|
558
671
|
self.name = name
|
|
559
672
|
self.property = property
|
|
560
673
|
self.index = 1
|
|
561
674
|
|
|
562
|
-
def add(self, name, x, y, w, h, text, value=None):
|
|
675
|
+
def add(self, name, x, y, w, h, text, value=None) -> None:
|
|
563
676
|
if value is None:
|
|
564
677
|
value = name
|
|
565
678
|
add_data(
|
|
@@ -573,7 +686,7 @@ class RadioButtonGroup(Control):
|
|
|
573
686
|
class Dialog:
|
|
574
687
|
def __init__(
|
|
575
688
|
self, db, name, x, y, w, h, attr, title, first, default, cancel
|
|
576
|
-
):
|
|
689
|
+
) -> None:
|
|
577
690
|
self.db = db
|
|
578
691
|
self.name = name
|
|
579
692
|
self.x, self.y, self.w, self.h = x, y, w, h
|
|
@@ -583,7 +696,9 @@ class Dialog:
|
|
|
583
696
|
[(name, x, y, w, h, attr, title, first, default, cancel)],
|
|
584
697
|
)
|
|
585
698
|
|
|
586
|
-
def control(
|
|
699
|
+
def control(
|
|
700
|
+
self, name, type, x, y, w, h, attr, prop, text, next, help
|
|
701
|
+
) -> Control:
|
|
587
702
|
add_data(
|
|
588
703
|
self.db,
|
|
589
704
|
"Control",
|
|
@@ -606,27 +721,27 @@ class Dialog:
|
|
|
606
721
|
)
|
|
607
722
|
return Control(self, name)
|
|
608
723
|
|
|
609
|
-
def text(self, name, x, y, w, h, attr, text):
|
|
724
|
+
def text(self, name, x, y, w, h, attr, text) -> Control:
|
|
610
725
|
return self.control(
|
|
611
726
|
name, "Text", x, y, w, h, attr, None, text, None, None
|
|
612
727
|
)
|
|
613
728
|
|
|
614
|
-
def bitmap(self, name, x, y, w, h, text):
|
|
729
|
+
def bitmap(self, name, x, y, w, h, text) -> Control:
|
|
615
730
|
return self.control(
|
|
616
731
|
name, "Bitmap", x, y, w, h, 1, None, text, None, None
|
|
617
732
|
)
|
|
618
733
|
|
|
619
|
-
def line(self, name, x, y, w, h):
|
|
734
|
+
def line(self, name, x, y, w, h) -> Control:
|
|
620
735
|
return self.control(
|
|
621
736
|
name, "Line", x, y, w, h, 1, None, None, None, None
|
|
622
737
|
)
|
|
623
738
|
|
|
624
|
-
def pushbutton(self, name, x, y, w, h, attr, text, next):
|
|
739
|
+
def pushbutton(self, name, x, y, w, h, attr, text, next) -> Control:
|
|
625
740
|
return self.control(
|
|
626
741
|
name, "PushButton", x, y, w, h, attr, None, text, next, None
|
|
627
742
|
)
|
|
628
743
|
|
|
629
|
-
def radiogroup(self, name, x, y, w, h, attr, prop, text, next):
|
|
744
|
+
def radiogroup(self, name, x, y, w, h, attr, prop, text, next) -> Control:
|
|
630
745
|
add_data(
|
|
631
746
|
self.db,
|
|
632
747
|
"Control",
|
|
@@ -649,7 +764,7 @@ class Dialog:
|
|
|
649
764
|
)
|
|
650
765
|
return RadioButtonGroup(self, name, prop)
|
|
651
766
|
|
|
652
|
-
def checkbox(self, name, x, y, w, h, attr, prop, text, next):
|
|
767
|
+
def checkbox(self, name, x, y, w, h, attr, prop, text, next) -> Control:
|
|
653
768
|
return self.control(
|
|
654
769
|
name, "CheckBox", x, y, w, h, attr, prop, text, next, None
|
|
655
770
|
)
|
msilib/_msi.c
CHANGED
|
@@ -298,8 +298,8 @@ static PyObject* _msi_FCICreate_impl(
|
|
|
298
298
|
return NULL;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
for (i = 0; i <
|
|
302
|
-
PyObject* item =
|
|
301
|
+
for (i = 0; i < PyList_Size(files); i++) {
|
|
302
|
+
PyObject* item = PyList_GetItemRef(files, i);
|
|
303
303
|
char *filename, *cabname;
|
|
304
304
|
|
|
305
305
|
if (!PyArg_ParseTuple(item, "ss", &filename, &cabname)) {
|
|
@@ -565,18 +565,11 @@ static PyObject* _msi_Record_SetInteger_impl(
|
|
|
565
565
|
Py_RETURN_NONE;
|
|
566
566
|
}
|
|
567
567
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
_MSI_RECORD_SETSTRING_METHODDEF
|
|
574
|
-
_MSI_RECORD_SETSTREAM_METHODDEF
|
|
575
|
-
_MSI_RECORD_SETINTEGER_METHODDEF
|
|
576
|
-
_MSI_RECORD_CLEARDATA_METHODDEF
|
|
577
|
-
{ NULL, NULL }
|
|
578
|
-
};
|
|
579
|
-
// clang-format on
|
|
568
|
+
static PyMethodDef record_methods[]
|
|
569
|
+
= { _MSI_RECORD_GETFIELDCOUNT_METHODDEF, _MSI_RECORD_GETINTEGER_METHODDEF,
|
|
570
|
+
_MSI_RECORD_GETSTRING_METHODDEF, _MSI_RECORD_SETSTRING_METHODDEF,
|
|
571
|
+
_MSI_RECORD_SETSTREAM_METHODDEF, _MSI_RECORD_SETINTEGER_METHODDEF,
|
|
572
|
+
_MSI_RECORD_CLEARDATA_METHODDEF, _MSI_SENTINEL };
|
|
580
573
|
|
|
581
574
|
static PyTypeObject record_Type = {
|
|
582
575
|
PyVarObject_HEAD_INIT(NULL, 0) "_msi.Record", /*tp_name*/
|
|
@@ -777,15 +770,11 @@ static PyObject* _msi_SummaryInformation_Persist_impl(msiobj* self)
|
|
|
777
770
|
Py_RETURN_NONE;
|
|
778
771
|
}
|
|
779
772
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
_MSI_SUMMARYINFORMATION_PERSIST_METHODDEF
|
|
786
|
-
{ NULL, NULL }
|
|
787
|
-
};
|
|
788
|
-
// clang-format on
|
|
773
|
+
static PyMethodDef summary_methods[]
|
|
774
|
+
= { _MSI_SUMMARYINFORMATION_GETPROPERTY_METHODDEF,
|
|
775
|
+
_MSI_SUMMARYINFORMATION_GETPROPERTYCOUNT_METHODDEF,
|
|
776
|
+
_MSI_SUMMARYINFORMATION_SETPROPERTY_METHODDEF,
|
|
777
|
+
_MSI_SUMMARYINFORMATION_PERSIST_METHODDEF, _MSI_SENTINEL };
|
|
789
778
|
|
|
790
779
|
static PyTypeObject summary_Type = {
|
|
791
780
|
PyVarObject_HEAD_INIT(NULL, 0) "_msi.SummaryInformation", /*tp_name*/
|
|
@@ -953,16 +942,9 @@ static PyObject* _msi_View_Close_impl(msiobj* self)
|
|
|
953
942
|
Py_RETURN_NONE;
|
|
954
943
|
}
|
|
955
944
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
_MSI_VIEW_GETCOLUMNINFO_METHODDEF
|
|
960
|
-
_MSI_VIEW_FETCH_METHODDEF
|
|
961
|
-
_MSI_VIEW_MODIFY_METHODDEF
|
|
962
|
-
_MSI_VIEW_CLOSE_METHODDEF
|
|
963
|
-
{ NULL, NULL }
|
|
964
|
-
};
|
|
965
|
-
// clang-format on
|
|
945
|
+
static PyMethodDef view_methods[] = { _MSI_VIEW_EXECUTE_METHODDEF,
|
|
946
|
+
_MSI_VIEW_GETCOLUMNINFO_METHODDEF, _MSI_VIEW_FETCH_METHODDEF,
|
|
947
|
+
_MSI_VIEW_MODIFY_METHODDEF, _MSI_VIEW_CLOSE_METHODDEF, _MSI_SENTINEL };
|
|
966
948
|
|
|
967
949
|
static PyTypeObject msiview_Type = {
|
|
968
950
|
PyVarObject_HEAD_INIT(NULL, 0) "_msi.View", /*tp_name*/
|
|
@@ -1086,15 +1068,10 @@ static PyObject* _msi_Database_GetSummaryInformation_impl(
|
|
|
1086
1068
|
return (PyObject*)oresult;
|
|
1087
1069
|
}
|
|
1088
1070
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
_MSI_DATABASE_GETSUMMARYINFORMATION_METHODDEF
|
|
1094
|
-
_MSI_DATABASE_CLOSE_METHODDEF
|
|
1095
|
-
{ NULL, NULL }
|
|
1096
|
-
};
|
|
1097
|
-
// clang-format on
|
|
1071
|
+
static PyMethodDef db_methods[]
|
|
1072
|
+
= { _MSI_DATABASE_OPENVIEW_METHODDEF, _MSI_DATABASE_COMMIT_METHODDEF,
|
|
1073
|
+
_MSI_DATABASE_GETSUMMARYINFORMATION_METHODDEF,
|
|
1074
|
+
_MSI_DATABASE_CLOSE_METHODDEF, _MSI_SENTINEL };
|
|
1098
1075
|
|
|
1099
1076
|
static PyTypeObject msidb_Type = {
|
|
1100
1077
|
PyVarObject_HEAD_INIT(NULL, 0) "_msi.Database", /*tp_name*/
|
|
@@ -1207,15 +1184,9 @@ static PyObject* _msi_CreateRecord_impl(PyObject* module, int count)
|
|
|
1207
1184
|
return record_new(h);
|
|
1208
1185
|
}
|
|
1209
1186
|
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
_MSI_FCICREATE_METHODDEF
|
|
1214
|
-
_MSI_OPENDATABASE_METHODDEF
|
|
1215
|
-
_MSI_CREATERECORD_METHODDEF
|
|
1216
|
-
{NULL, NULL} /* sentinel */
|
|
1217
|
-
};
|
|
1218
|
-
// clang-format on
|
|
1187
|
+
static PyMethodDef msi_methods[] = { _MSI_UUIDCREATE_METHODDEF,
|
|
1188
|
+
_MSI_FCICREATE_METHODDEF, _MSI_OPENDATABASE_METHODDEF,
|
|
1189
|
+
_MSI_CREATERECORD_METHODDEF, _MSI_SENTINEL };
|
|
1219
1190
|
|
|
1220
1191
|
static char msi_doc[] = "Documentation";
|
|
1221
1192
|
|
|
@@ -1282,5 +1253,8 @@ PyMODINIT_FUNC PyInit__msi(void)
|
|
|
1282
1253
|
if (!MSIError)
|
|
1283
1254
|
return NULL;
|
|
1284
1255
|
PyModule_AddObject(m, "MSIError", MSIError);
|
|
1256
|
+
#ifdef Py_GIL_DISABLED
|
|
1257
|
+
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
|
|
1258
|
+
#endif
|
|
1285
1259
|
return m;
|
|
1286
1260
|
}
|
msilib/_msi.cp313-win32.pyd
CHANGED
|
Binary file
|
msilib/include/_msi.h
CHANGED
|
@@ -6,6 +6,8 @@ preserve
|
|
|
6
6
|
#define Py_BUILD_CORE
|
|
7
7
|
#include <internal/pycore_modsupport.h>
|
|
8
8
|
|
|
9
|
+
#define _MSI_SENTINEL { NULL, NULL }
|
|
10
|
+
|
|
9
11
|
PyDoc_STRVAR(_msi_UuidCreate__doc__,
|
|
10
12
|
"UuidCreate($module, /)\n"
|
|
11
13
|
"--\n"
|
|
@@ -14,7 +16,7 @@ PyDoc_STRVAR(_msi_UuidCreate__doc__,
|
|
|
14
16
|
|
|
15
17
|
#define _MSI_UUIDCREATE_METHODDEF \
|
|
16
18
|
{ "UuidCreate", (PyCFunction)_msi_UuidCreate, METH_NOARGS, \
|
|
17
|
-
_msi_UuidCreate__doc__ }
|
|
19
|
+
_msi_UuidCreate__doc__ }
|
|
18
20
|
|
|
19
21
|
static PyObject* _msi_UuidCreate_impl(PyObject* module);
|
|
20
22
|
|
|
@@ -38,7 +40,7 @@ PyDoc_STRVAR(_msi_FCICreate__doc__,
|
|
|
38
40
|
|
|
39
41
|
#define _MSI_FCICREATE_METHODDEF \
|
|
40
42
|
{ "FCICreate", _PyCFunction_CAST(_msi_FCICreate), METH_FASTCALL, \
|
|
41
|
-
_msi_FCICreate__doc__ }
|
|
43
|
+
_msi_FCICreate__doc__ }
|
|
42
44
|
|
|
43
45
|
static PyObject* _msi_FCICreate_impl(
|
|
44
46
|
PyObject* module, const char* cabname, PyObject* files);
|
|
@@ -81,7 +83,7 @@ PyDoc_STRVAR(_msi_Database_Close__doc__,
|
|
|
81
83
|
|
|
82
84
|
#define _MSI_DATABASE_CLOSE_METHODDEF \
|
|
83
85
|
{ "Close", (PyCFunction)_msi_Database_Close, METH_NOARGS, \
|
|
84
|
-
_msi_Database_Close__doc__ }
|
|
86
|
+
_msi_Database_Close__doc__ }
|
|
85
87
|
|
|
86
88
|
static PyObject* _msi_Database_Close_impl(msiobj* self);
|
|
87
89
|
|
|
@@ -99,7 +101,7 @@ PyDoc_STRVAR(_msi_Record_GetFieldCount__doc__,
|
|
|
99
101
|
|
|
100
102
|
#define _MSI_RECORD_GETFIELDCOUNT_METHODDEF \
|
|
101
103
|
{ "GetFieldCount", (PyCFunction)_msi_Record_GetFieldCount, METH_NOARGS, \
|
|
102
|
-
_msi_Record_GetFieldCount__doc__ }
|
|
104
|
+
_msi_Record_GetFieldCount__doc__ }
|
|
103
105
|
|
|
104
106
|
static PyObject* _msi_Record_GetFieldCount_impl(msiobj* self);
|
|
105
107
|
|
|
@@ -117,7 +119,7 @@ PyDoc_STRVAR(_msi_Record_GetInteger__doc__,
|
|
|
117
119
|
|
|
118
120
|
#define _MSI_RECORD_GETINTEGER_METHODDEF \
|
|
119
121
|
{ "GetInteger", (PyCFunction)_msi_Record_GetInteger, METH_O, \
|
|
120
|
-
_msi_Record_GetInteger__doc__ }
|
|
122
|
+
_msi_Record_GetInteger__doc__ }
|
|
121
123
|
|
|
122
124
|
static PyObject* _msi_Record_GetInteger_impl(msiobj* self, unsigned int field);
|
|
123
125
|
|
|
@@ -144,7 +146,7 @@ PyDoc_STRVAR(_msi_Record_GetString__doc__,
|
|
|
144
146
|
|
|
145
147
|
#define _MSI_RECORD_GETSTRING_METHODDEF \
|
|
146
148
|
{ "GetString", (PyCFunction)_msi_Record_GetString, METH_O, \
|
|
147
|
-
_msi_Record_GetString__doc__ }
|
|
149
|
+
_msi_Record_GetString__doc__ }
|
|
148
150
|
|
|
149
151
|
static PyObject* _msi_Record_GetString_impl(msiobj* self, unsigned int field);
|
|
150
152
|
|
|
@@ -171,7 +173,7 @@ PyDoc_STRVAR(_msi_Record_ClearData__doc__,
|
|
|
171
173
|
|
|
172
174
|
#define _MSI_RECORD_CLEARDATA_METHODDEF \
|
|
173
175
|
{ "ClearData", (PyCFunction)_msi_Record_ClearData, METH_NOARGS, \
|
|
174
|
-
_msi_Record_ClearData__doc__ }
|
|
176
|
+
_msi_Record_ClearData__doc__ }
|
|
175
177
|
|
|
176
178
|
static PyObject* _msi_Record_ClearData_impl(msiobj* self);
|
|
177
179
|
|
|
@@ -189,7 +191,7 @@ PyDoc_STRVAR(_msi_Record_SetString__doc__,
|
|
|
189
191
|
|
|
190
192
|
#define _MSI_RECORD_SETSTRING_METHODDEF \
|
|
191
193
|
{ "SetString", _PyCFunction_CAST(_msi_Record_SetString), METH_FASTCALL, \
|
|
192
|
-
_msi_Record_SetString__doc__ }
|
|
194
|
+
_msi_Record_SetString__doc__ }
|
|
193
195
|
|
|
194
196
|
static PyObject* _msi_Record_SetString_impl(
|
|
195
197
|
msiobj* self, int field, const wchar_t* value);
|
|
@@ -233,7 +235,7 @@ PyDoc_STRVAR(_msi_Record_SetStream__doc__,
|
|
|
233
235
|
|
|
234
236
|
#define _MSI_RECORD_SETSTREAM_METHODDEF \
|
|
235
237
|
{ "SetStream", _PyCFunction_CAST(_msi_Record_SetStream), METH_FASTCALL, \
|
|
236
|
-
_msi_Record_SetStream__doc__ }
|
|
238
|
+
_msi_Record_SetStream__doc__ }
|
|
237
239
|
|
|
238
240
|
static PyObject* _msi_Record_SetStream_impl(
|
|
239
241
|
msiobj* self, int field, const wchar_t* value);
|
|
@@ -277,7 +279,7 @@ PyDoc_STRVAR(_msi_Record_SetInteger__doc__,
|
|
|
277
279
|
|
|
278
280
|
#define _MSI_RECORD_SETINTEGER_METHODDEF \
|
|
279
281
|
{ "SetInteger", _PyCFunction_CAST(_msi_Record_SetInteger), METH_FASTCALL, \
|
|
280
|
-
_msi_Record_SetInteger__doc__ }
|
|
282
|
+
_msi_Record_SetInteger__doc__ }
|
|
281
283
|
|
|
282
284
|
static PyObject* _msi_Record_SetInteger_impl(
|
|
283
285
|
msiobj* self, int field, int value);
|
|
@@ -317,7 +319,7 @@ PyDoc_STRVAR(_msi_SummaryInformation_GetProperty__doc__,
|
|
|
317
319
|
|
|
318
320
|
#define _MSI_SUMMARYINFORMATION_GETPROPERTY_METHODDEF \
|
|
319
321
|
{ "GetProperty", (PyCFunction)_msi_SummaryInformation_GetProperty, \
|
|
320
|
-
METH_O, _msi_SummaryInformation_GetProperty__doc__ }
|
|
322
|
+
METH_O, _msi_SummaryInformation_GetProperty__doc__ }
|
|
321
323
|
|
|
322
324
|
static PyObject* _msi_SummaryInformation_GetProperty_impl(
|
|
323
325
|
msiobj* self, int field);
|
|
@@ -347,7 +349,7 @@ PyDoc_STRVAR(_msi_SummaryInformation_GetPropertyCount__doc__,
|
|
|
347
349
|
#define _MSI_SUMMARYINFORMATION_GETPROPERTYCOUNT_METHODDEF \
|
|
348
350
|
{ "GetPropertyCount", \
|
|
349
351
|
(PyCFunction)_msi_SummaryInformation_GetPropertyCount, METH_NOARGS, \
|
|
350
|
-
_msi_SummaryInformation_GetPropertyCount__doc__ }
|
|
352
|
+
_msi_SummaryInformation_GetPropertyCount__doc__ }
|
|
351
353
|
|
|
352
354
|
static PyObject* _msi_SummaryInformation_GetPropertyCount_impl(msiobj* self);
|
|
353
355
|
|
|
@@ -370,7 +372,7 @@ PyDoc_STRVAR(_msi_SummaryInformation_SetProperty__doc__,
|
|
|
370
372
|
|
|
371
373
|
#define _MSI_SUMMARYINFORMATION_SETPROPERTY_METHODDEF \
|
|
372
374
|
{ "SetProperty", _PyCFunction_CAST(_msi_SummaryInformation_SetProperty), \
|
|
373
|
-
METH_FASTCALL, _msi_SummaryInformation_SetProperty__doc__ }
|
|
375
|
+
METH_FASTCALL, _msi_SummaryInformation_SetProperty__doc__ }
|
|
374
376
|
|
|
375
377
|
static PyObject* _msi_SummaryInformation_SetProperty_impl(
|
|
376
378
|
msiobj* self, int field, PyObject* data);
|
|
@@ -404,7 +406,7 @@ PyDoc_STRVAR(_msi_SummaryInformation_Persist__doc__,
|
|
|
404
406
|
|
|
405
407
|
#define _MSI_SUMMARYINFORMATION_PERSIST_METHODDEF \
|
|
406
408
|
{ "Persist", (PyCFunction)_msi_SummaryInformation_Persist, METH_NOARGS, \
|
|
407
|
-
_msi_SummaryInformation_Persist__doc__ }
|
|
409
|
+
_msi_SummaryInformation_Persist__doc__ }
|
|
408
410
|
|
|
409
411
|
static PyObject* _msi_SummaryInformation_Persist_impl(msiobj* self);
|
|
410
412
|
|
|
@@ -426,7 +428,7 @@ PyDoc_STRVAR(_msi_View_Execute__doc__,
|
|
|
426
428
|
|
|
427
429
|
#define _MSI_VIEW_EXECUTE_METHODDEF \
|
|
428
430
|
{ "Execute", (PyCFunction)_msi_View_Execute, METH_O, \
|
|
429
|
-
_msi_View_Execute__doc__ }
|
|
431
|
+
_msi_View_Execute__doc__ }
|
|
430
432
|
|
|
431
433
|
PyDoc_STRVAR(_msi_View_Fetch__doc__,
|
|
432
434
|
"Fetch($self, /)\n"
|
|
@@ -436,7 +438,7 @@ PyDoc_STRVAR(_msi_View_Fetch__doc__,
|
|
|
436
438
|
|
|
437
439
|
#define _MSI_VIEW_FETCH_METHODDEF \
|
|
438
440
|
{ "Fetch", (PyCFunction)_msi_View_Fetch, METH_NOARGS, \
|
|
439
|
-
_msi_View_Fetch__doc__ }
|
|
441
|
+
_msi_View_Fetch__doc__ }
|
|
440
442
|
|
|
441
443
|
static PyObject* _msi_View_Fetch_impl(msiobj* self);
|
|
442
444
|
|
|
@@ -456,7 +458,7 @@ PyDoc_STRVAR(_msi_View_GetColumnInfo__doc__,
|
|
|
456
458
|
|
|
457
459
|
#define _MSI_VIEW_GETCOLUMNINFO_METHODDEF \
|
|
458
460
|
{ "GetColumnInfo", (PyCFunction)_msi_View_GetColumnInfo, METH_O, \
|
|
459
|
-
_msi_View_GetColumnInfo__doc__ }
|
|
461
|
+
_msi_View_GetColumnInfo__doc__ }
|
|
460
462
|
|
|
461
463
|
static PyObject* _msi_View_GetColumnInfo_impl(msiobj* self, int kind);
|
|
462
464
|
|
|
@@ -488,7 +490,7 @@ PyDoc_STRVAR(_msi_View_Modify__doc__,
|
|
|
488
490
|
|
|
489
491
|
#define _MSI_VIEW_MODIFY_METHODDEF \
|
|
490
492
|
{ "Modify", _PyCFunction_CAST(_msi_View_Modify), METH_FASTCALL, \
|
|
491
|
-
_msi_View_Modify__doc__ }
|
|
493
|
+
_msi_View_Modify__doc__ }
|
|
492
494
|
|
|
493
495
|
static PyObject* _msi_View_Modify_impl(msiobj* self, int kind, PyObject* data);
|
|
494
496
|
|
|
@@ -521,7 +523,7 @@ PyDoc_STRVAR(_msi_View_Close__doc__,
|
|
|
521
523
|
|
|
522
524
|
#define _MSI_VIEW_CLOSE_METHODDEF \
|
|
523
525
|
{ "Close", (PyCFunction)_msi_View_Close, METH_NOARGS, \
|
|
524
|
-
_msi_View_Close__doc__ }
|
|
526
|
+
_msi_View_Close__doc__ }
|
|
525
527
|
|
|
526
528
|
static PyObject* _msi_View_Close_impl(msiobj* self);
|
|
527
529
|
|
|
@@ -541,7 +543,7 @@ PyDoc_STRVAR(_msi_Database_OpenView__doc__,
|
|
|
541
543
|
|
|
542
544
|
#define _MSI_DATABASE_OPENVIEW_METHODDEF \
|
|
543
545
|
{ "OpenView", (PyCFunction)_msi_Database_OpenView, METH_O, \
|
|
544
|
-
_msi_Database_OpenView__doc__ }
|
|
546
|
+
_msi_Database_OpenView__doc__ }
|
|
545
547
|
|
|
546
548
|
static PyObject* _msi_Database_OpenView_impl(msiobj* self, const wchar_t* sql);
|
|
547
549
|
|
|
@@ -575,7 +577,7 @@ PyDoc_STRVAR(_msi_Database_Commit__doc__,
|
|
|
575
577
|
|
|
576
578
|
#define _MSI_DATABASE_COMMIT_METHODDEF \
|
|
577
579
|
{ "Commit", (PyCFunction)_msi_Database_Commit, METH_NOARGS, \
|
|
578
|
-
_msi_Database_Commit__doc__ }
|
|
580
|
+
_msi_Database_Commit__doc__ }
|
|
579
581
|
|
|
580
582
|
static PyObject* _msi_Database_Commit_impl(msiobj* self);
|
|
581
583
|
|
|
@@ -597,7 +599,7 @@ PyDoc_STRVAR(_msi_Database_GetSummaryInformation__doc__,
|
|
|
597
599
|
#define _MSI_DATABASE_GETSUMMARYINFORMATION_METHODDEF \
|
|
598
600
|
{ "GetSummaryInformation", \
|
|
599
601
|
(PyCFunction)_msi_Database_GetSummaryInformation, METH_O, \
|
|
600
|
-
_msi_Database_GetSummaryInformation__doc__ }
|
|
602
|
+
_msi_Database_GetSummaryInformation__doc__ }
|
|
601
603
|
|
|
602
604
|
static PyObject* _msi_Database_GetSummaryInformation_impl(
|
|
603
605
|
msiobj* self, int count);
|
|
@@ -631,7 +633,7 @@ PyDoc_STRVAR(_msi_OpenDatabase__doc__,
|
|
|
631
633
|
|
|
632
634
|
#define _MSI_OPENDATABASE_METHODDEF \
|
|
633
635
|
{ "OpenDatabase", _PyCFunction_CAST(_msi_OpenDatabase), METH_FASTCALL, \
|
|
634
|
-
_msi_OpenDatabase__doc__ }
|
|
636
|
+
_msi_OpenDatabase__doc__ }
|
|
635
637
|
|
|
636
638
|
static PyObject* _msi_OpenDatabase_impl(
|
|
637
639
|
PyObject* module, const wchar_t* path, int persist);
|
|
@@ -678,7 +680,7 @@ PyDoc_STRVAR(_msi_CreateRecord__doc__,
|
|
|
678
680
|
|
|
679
681
|
#define _MSI_CREATERECORD_METHODDEF \
|
|
680
682
|
{ "CreateRecord", (PyCFunction)_msi_CreateRecord, METH_O, \
|
|
681
|
-
_msi_CreateRecord__doc__ }
|
|
683
|
+
_msi_CreateRecord__doc__ }
|
|
682
684
|
|
|
683
685
|
static PyObject* _msi_CreateRecord_impl(PyObject* module, int count);
|
|
684
686
|
|
|
@@ -1991,7 +1991,7 @@ static inline int Py_fclose(FILE *file)
|
|
|
1991
1991
|
#endif
|
|
1992
1992
|
|
|
1993
1993
|
|
|
1994
|
-
#if
|
|
1994
|
+
#if 0x03080000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION)
|
|
1995
1995
|
static inline PyObject*
|
|
1996
1996
|
PyConfig_Get(const char *name)
|
|
1997
1997
|
{
|
|
@@ -2032,7 +2032,9 @@ PyConfig_Get(const char *name)
|
|
|
2032
2032
|
PYTHONCAPI_COMPAT_SPEC(module_search_paths, WSTR_LIST, "path"),
|
|
2033
2033
|
PYTHONCAPI_COMPAT_SPEC(optimization_level, UINT, _Py_NULL),
|
|
2034
2034
|
PYTHONCAPI_COMPAT_SPEC(parser_debug, BOOL, _Py_NULL),
|
|
2035
|
+
#if 0x03090000 <= PY_VERSION_HEX
|
|
2035
2036
|
PYTHONCAPI_COMPAT_SPEC(platlibdir, WSTR, "platlibdir"),
|
|
2037
|
+
#endif
|
|
2036
2038
|
PYTHONCAPI_COMPAT_SPEC(prefix, WSTR_OPT, "prefix"),
|
|
2037
2039
|
PYTHONCAPI_COMPAT_SPEC(pycache_prefix, WSTR_OPT, "pycache_prefix"),
|
|
2038
2040
|
PYTHONCAPI_COMPAT_SPEC(quiet, BOOL, _Py_NULL),
|
|
@@ -2529,6 +2531,10 @@ PyBytesWriter_WriteBytes(PyBytesWriter *writer,
|
|
|
2529
2531
|
return 0;
|
|
2530
2532
|
}
|
|
2531
2533
|
|
|
2534
|
+
static inline int
|
|
2535
|
+
PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...)
|
|
2536
|
+
Py_GCC_ATTRIBUTE((format(printf, 2, 3)));
|
|
2537
|
+
|
|
2532
2538
|
static inline int
|
|
2533
2539
|
PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...)
|
|
2534
2540
|
{
|
|
@@ -2549,6 +2555,39 @@ PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...)
|
|
|
2549
2555
|
#endif // PY_VERSION_HEX < 0x030F00A1
|
|
2550
2556
|
|
|
2551
2557
|
|
|
2558
|
+
#if PY_VERSION_HEX < 0x030F00A1
|
|
2559
|
+
static inline PyObject*
|
|
2560
|
+
PyTuple_FromArray(PyObject *const *array, Py_ssize_t size)
|
|
2561
|
+
{
|
|
2562
|
+
PyObject *tuple = PyTuple_New(size);
|
|
2563
|
+
if (tuple == NULL) {
|
|
2564
|
+
return NULL;
|
|
2565
|
+
}
|
|
2566
|
+
for (Py_ssize_t i=0; i < size; i++) {
|
|
2567
|
+
PyObject *item = array[i];
|
|
2568
|
+
PyTuple_SET_ITEM(tuple, i, Py_NewRef(item));
|
|
2569
|
+
}
|
|
2570
|
+
return tuple;
|
|
2571
|
+
}
|
|
2572
|
+
#endif
|
|
2573
|
+
|
|
2574
|
+
|
|
2575
|
+
#if PY_VERSION_HEX < 0x030F00A1
|
|
2576
|
+
static inline Py_hash_t
|
|
2577
|
+
PyUnstable_Unicode_GET_CACHED_HASH(PyObject *op)
|
|
2578
|
+
{
|
|
2579
|
+
#ifdef PYPY_VERSION
|
|
2580
|
+
(void)op; // unused argument
|
|
2581
|
+
return -1;
|
|
2582
|
+
#elif PY_VERSION_HEX >= 0x03000000
|
|
2583
|
+
return ((PyASCIIObject*)op)->hash;
|
|
2584
|
+
#else
|
|
2585
|
+
return ((PyUnicodeObject*)op)->hash;
|
|
2586
|
+
#endif
|
|
2587
|
+
}
|
|
2588
|
+
#endif
|
|
2589
|
+
|
|
2590
|
+
|
|
2552
2591
|
#ifdef __cplusplus
|
|
2553
2592
|
}
|
|
2554
2593
|
#endif
|
msilib/schema.py
CHANGED
msilib/sequence.py
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
"""Table contents for the standard sequence tables:
|
|
2
|
+
AdminExecuteSequence, AdminUISequence, AdvtExecuteSequence,
|
|
3
|
+
InstallExecuteSequence, and InstallUISequence.
|
|
4
|
+
"""
|
|
5
|
+
|
|
1
6
|
AdminExecuteSequence = [
|
|
2
7
|
("InstallInitialize", None, 1500),
|
|
3
8
|
("InstallFinalize", None, 6600),
|
msilib/text.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-msilib
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Read and write Microsoft Installer files
|
|
5
5
|
Author-email: Marcelo Duarte <marcelotduarte@users.noreply.github.com>
|
|
6
6
|
License-Expression: PSF-2.0
|
|
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
|
|
19
20
|
Classifier: Topic :: Software Development :: Build Tools
|
|
20
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
22
|
Classifier: Topic :: System :: Software Distribution
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
msilib/__init__.py,sha256=IQGo-bdp711AtRjjgpiIZK9sH2kuRTBcMezHYDm-1zc,23156
|
|
2
|
+
msilib/_msi.c,sha256=xPgxiCH___904SmeJf6SxZ4m7Q1chSi9JlKsSx592ko,38426
|
|
3
|
+
msilib/_msi.cp313-win32.pyd,sha256=bXrZwromTcbuIz3ZrKuoT1-vI8ecV1tFCm8eHXRKJE4,26112
|
|
4
|
+
msilib/schema.py,sha256=USaXE5O_3pkt8VLbJcSIjhTtvOgprJgjoRn9wMvIJv4,128781
|
|
5
|
+
msilib/sequence.py,sha256=MF0rHrOQ1WX-cQ9oFRV55Snk6Fa9wJqgSOSNIpErDME,4695
|
|
6
|
+
msilib/text.py,sha256=XbcropSwKsrL5WoNTiW-Lbmj9CGY3r4op4ENHfPki94,11129
|
|
7
|
+
msilib/include/_msi.h,sha256=hDS-3E6dRHj8f6sg3FArpD1CHM9m8kGfH5gDYD8eang,20945
|
|
8
|
+
msilib/include/pythoncapi_compat.h,sha256=ntwNXFRDLa7FFJ1dVrlBRK0S_ms8aKD7t1XXoN6u4Bo,73222
|
|
9
|
+
python_msilib-0.4.0.dist-info/licenses/LICENSE,sha256=Wju9Q0A41nBaSfjgklLmLoONJJJSYQD8agr81R5HUnI,2584
|
|
10
|
+
python_msilib-0.4.0.dist-info/METADATA,sha256=R_e3MBULhS86v1vLewMtdMN17AB2k49BzK2C5Fj9xnk,3652
|
|
11
|
+
python_msilib-0.4.0.dist-info/WHEEL,sha256=0ABLuJ37exXk5N_efmYNs2NU9NK1K2Qlod_6bYkofEA,97
|
|
12
|
+
python_msilib-0.4.0.dist-info/top_level.txt,sha256=reGDwqhWKgUpH6z4VDR3W4MUnrUixkQv8pFZxMzH4Es,7
|
|
13
|
+
python_msilib-0.4.0.dist-info/RECORD,,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
msilib/__init__.py,sha256=fm5yUVNBZHd4B5jMZES1GkFfJ5NYREkgn5feuRBuneM,20135
|
|
2
|
-
msilib/_msi.c,sha256=FRB1t_4pjDRDg5r2DuzaqDgr0ymxIiqMCfWWlFtPJ1k,38606
|
|
3
|
-
msilib/_msi.cp313-win32.pyd,sha256=XD8zV1uq0dl6RrhUA0MCGyo6Y-ZA37MktydpmcqZnDU,26112
|
|
4
|
-
msilib/schema.py,sha256=_qBk8geNrA5Iup92yLvv8rgbx4EUSyA0BoPxqT6Q95U,128604
|
|
5
|
-
msilib/sequence.py,sha256=m1Yo_u1JGuGpHydHVNJFHvvXMZ3wBU-yHWq9px6ed1I,4526
|
|
6
|
-
msilib/text.py,sha256=Xd4CFDmgChKgIf6qsc6IFzT4YmJYXH8TqPm1W6GOW10,11039
|
|
7
|
-
msilib/include/_msi.h,sha256=sPtYIxAB6HS6K3_MWHpcd639whVvTqt78Pumt77l_gI,20929
|
|
8
|
-
msilib/include/pythoncapi_compat.h,sha256=xReZ1yVIyHzdoO05n4XKf9iNLqFfDF1WjWV2YtQdREo,72302
|
|
9
|
-
python_msilib-0.2.0.dist-info/licenses/LICENSE,sha256=Wju9Q0A41nBaSfjgklLmLoONJJJSYQD8agr81R5HUnI,2584
|
|
10
|
-
python_msilib-0.2.0.dist-info/METADATA,sha256=skRbJyYS-VjtCM0RixXvCiqvhCWhSrBfoaGb3i11RaE,3578
|
|
11
|
-
python_msilib-0.2.0.dist-info/WHEEL,sha256=0ABLuJ37exXk5N_efmYNs2NU9NK1K2Qlod_6bYkofEA,97
|
|
12
|
-
python_msilib-0.2.0.dist-info/top_level.txt,sha256=reGDwqhWKgUpH6z4VDR3W4MUnrUixkQv8pFZxMzH4Es,7
|
|
13
|
-
python_msilib-0.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|