gh-104773: Remove the msilib package (GH-104911)

This commit is contained in:
Zachary Ware 2023-05-24 20:06:00 -05:00 committed by GitHub
parent 41768a2bd3
commit 98c4333e88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 22 additions and 4650 deletions

View File

@ -1,565 +0,0 @@
:mod:`msilib` --- Read and write Microsoft Installer files
==========================================================
.. module:: msilib
:platform: Windows
:synopsis: Creation of Microsoft Installer files, and CAB files.
:deprecated:
.. moduleauthor:: Martin v. Löwis <martin@v.loewis.de>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
**Source code:** :source:`Lib/msilib/__init__.py`
.. index:: single: msi
.. deprecated-removed:: 3.11 3.13
The :mod:`msilib` module is deprecated
(see :pep:`PEP 594 <594#msilib>` for details).
--------------
The :mod:`msilib` supports the creation of Microsoft Installer (``.msi``) files.
Because these files often contain an embedded "cabinet" file (``.cab``), it also
exposes an API to create CAB files. Support for reading ``.cab`` files is
currently not implemented; read support for the ``.msi`` database is possible.
This package aims to provide complete access to all tables in an ``.msi`` file,
therefore, it is a fairly low-level API. One primary application of this
package is the creation of Python installer package itself (although that currently
uses a different version of ``msilib``).
The package contents can be roughly split into four parts: low-level CAB
routines, low-level MSI routines, higher-level MSI routines, and standard table
structures.
.. function:: FCICreate(cabname, files)
Create a new CAB file named *cabname*. *files* must be a list of tuples, each
containing the name of the file on disk, and the name of the file inside the CAB
file.
The files are added to the CAB file in the order they appear in the list. All
files are added into a single CAB file, using the MSZIP compression algorithm.
Callbacks to Python for the various steps of MSI creation are currently not
exposed.
.. function:: UuidCreate()
Return the string representation of a new unique identifier. This wraps the
Windows API functions :c:func:`UuidCreate` and :c:func:`UuidToString`.
.. function:: OpenDatabase(path, persist)
Return a new database object by calling MsiOpenDatabase. *path* is the file
name of the MSI file; *persist* can be one of the constants
``MSIDBOPEN_CREATEDIRECT``, ``MSIDBOPEN_CREATE``, ``MSIDBOPEN_DIRECT``,
``MSIDBOPEN_READONLY``, or ``MSIDBOPEN_TRANSACT``, and may include the flag
``MSIDBOPEN_PATCHFILE``. See the Microsoft documentation for the meaning of
these flags; depending on the flags, an existing database is opened, or a new
one created.
.. function:: CreateRecord(count)
Return a new record object by calling :c:func:`MSICreateRecord`. *count* is the
number of fields of the record.
.. function:: init_database(name, schema, ProductName, ProductCode, ProductVersion, Manufacturer)
Create and return a new database *name*, initialize it with *schema*, and set
the properties *ProductName*, *ProductCode*, *ProductVersion*, and
*Manufacturer*.
*schema* must be a module object containing ``tables`` and
``_Validation_records`` attributes; typically, :mod:`msilib.schema` should be
used.
The database will contain just the schema and the validation records when this
function returns.
.. function:: add_data(database, table, records)
Add all *records* to the table named *table* in *database*.
The *table* argument must be one of the predefined tables in the MSI schema,
e.g. ``'Feature'``, ``'File'``, ``'Component'``, ``'Dialog'``, ``'Control'``,
etc.
*records* should be a list of tuples, each one containing all fields of a
record according to the schema of the table. For optional fields,
``None`` can be passed.
Field values can be ints, strings, or instances of the Binary class.
.. class:: Binary(filename)
Represents entries in the Binary table; inserting such an object using
:func:`add_data` reads the file named *filename* into the table.
.. function:: add_tables(database, module)
Add all table content from *module* to *database*. *module* must contain an
attribute *tables* listing all tables for which content should be added, and one
attribute per table that has the actual content.
This is typically used to install the sequence tables.
.. function:: add_stream(database, name, path)
Add the file *path* into the ``_Stream`` table of *database*, with the stream
name *name*.
.. function:: gen_uuid()
Return a new UUID, in the format that MSI typically requires (i.e. in curly
braces, and with all hexdigits in uppercase).
.. seealso::
`FCICreate <https://msdn.microsoft.com/en-us/library/bb432265.aspx>`_
`UuidCreate <https://msdn.microsoft.com/en-us/library/windows/desktop/aa379205.aspx>`_
`UuidToString <https://msdn.microsoft.com/en-us/library/windows/desktop/aa379352.aspx>`_
.. _database-objects:
Database Objects
----------------
.. method:: Database.OpenView(sql)
Return a view object, by calling :c:func:`MSIDatabaseOpenView`. *sql* is the SQL
statement to execute.
.. method:: Database.Commit()
Commit the changes pending in the current transaction, by calling
:c:func:`MSIDatabaseCommit`.
.. method:: Database.GetSummaryInformation(count)
Return a new summary information object, by calling
:c:func:`MsiGetSummaryInformation`. *count* is the maximum number of updated
values.
.. method:: Database.Close()
Close the database object, through :c:func:`MsiCloseHandle`.
.. versionadded:: 3.7
.. seealso::
`MSIDatabaseOpenView <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370082.aspx>`_
`MSIDatabaseCommit <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370075.aspx>`_
`MSIGetSummaryInformation <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370301.aspx>`_
`MsiCloseHandle <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370067.aspx>`_
.. _view-objects:
View Objects
------------
.. method:: View.Execute(params)
Execute the SQL query of the view, through :c:func:`MSIViewExecute`. If
*params* is not ``None``, it is a record describing actual values of the
parameter tokens in the query.
.. method:: View.GetColumnInfo(kind)
Return a record describing the columns of the view, through calling
:c:func:`MsiViewGetColumnInfo`. *kind* can be either ``MSICOLINFO_NAMES`` or
``MSICOLINFO_TYPES``.
.. method:: View.Fetch()
Return a result record of the query, through calling :c:func:`MsiViewFetch`.
.. method:: View.Modify(kind, data)
Modify the view, by calling :c:func:`MsiViewModify`. *kind* can be one of
``MSIMODIFY_SEEK``, ``MSIMODIFY_REFRESH``, ``MSIMODIFY_INSERT``,
``MSIMODIFY_UPDATE``, ``MSIMODIFY_ASSIGN``, ``MSIMODIFY_REPLACE``,
``MSIMODIFY_MERGE``, ``MSIMODIFY_DELETE``, ``MSIMODIFY_INSERT_TEMPORARY``,
``MSIMODIFY_VALIDATE``, ``MSIMODIFY_VALIDATE_NEW``,
``MSIMODIFY_VALIDATE_FIELD``, or ``MSIMODIFY_VALIDATE_DELETE``.
*data* must be a record describing the new data.
.. method:: View.Close()
Close the view, through :c:func:`MsiViewClose`.
.. seealso::
`MsiViewExecute <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370513.aspx>`_
`MSIViewGetColumnInfo <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370516.aspx>`_
`MsiViewFetch <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370514.aspx>`_
`MsiViewModify <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370519.aspx>`_
`MsiViewClose <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370510.aspx>`_
.. _summary-objects:
Summary Information Objects
---------------------------
.. method:: SummaryInformation.GetProperty(field)
Return a property of the summary, through :c:func:`MsiSummaryInfoGetProperty`.
*field* is the name of the property, and can be one of the constants
``PID_CODEPAGE``, ``PID_TITLE``, ``PID_SUBJECT``, ``PID_AUTHOR``,
``PID_KEYWORDS``, ``PID_COMMENTS``, ``PID_TEMPLATE``, ``PID_LASTAUTHOR``,
``PID_REVNUMBER``, ``PID_LASTPRINTED``, ``PID_CREATE_DTM``,
``PID_LASTSAVE_DTM``, ``PID_PAGECOUNT``, ``PID_WORDCOUNT``, ``PID_CHARCOUNT``,
``PID_APPNAME``, or ``PID_SECURITY``.
.. method:: SummaryInformation.GetPropertyCount()
Return the number of summary properties, through
:c:func:`MsiSummaryInfoGetPropertyCount`.
.. method:: SummaryInformation.SetProperty(field, value)
Set a property through :c:func:`MsiSummaryInfoSetProperty`. *field* can have the
same values as in :meth:`GetProperty`, *value* is the new value of the property.
Possible value types are integer and string.
.. method:: SummaryInformation.Persist()
Write the modified properties to the summary information stream, using
:c:func:`MsiSummaryInfoPersist`.
.. seealso::
`MsiSummaryInfoGetProperty <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370409.aspx>`_
`MsiSummaryInfoGetPropertyCount <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370488.aspx>`_
`MsiSummaryInfoSetProperty <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370491.aspx>`_
`MsiSummaryInfoPersist <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370490.aspx>`_
.. _record-objects:
Record Objects
--------------
.. method:: Record.GetFieldCount()
Return the number of fields of the record, through
:c:func:`MsiRecordGetFieldCount`.
.. method:: Record.GetInteger(field)
Return the value of *field* as an integer where possible. *field* must
be an integer.
.. method:: Record.GetString(field)
Return the value of *field* as a string where possible. *field* must
be an integer.
.. method:: Record.SetString(field, value)
Set *field* to *value* through :c:func:`MsiRecordSetString`. *field* must be an
integer; *value* a string.
.. method:: Record.SetStream(field, value)
Set *field* to the contents of the file named *value*, through
:c:func:`MsiRecordSetStream`. *field* must be an integer; *value* a string.
.. method:: Record.SetInteger(field, value)
Set *field* to *value* through :c:func:`MsiRecordSetInteger`. Both *field* and
*value* must be an integer.
.. method:: Record.ClearData()
Set all fields of the record to 0, through :c:func:`MsiRecordClearData`.
.. seealso::
`MsiRecordGetFieldCount <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370366.aspx>`_
`MsiRecordSetString <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370373.aspx>`_
`MsiRecordSetStream <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370372.aspx>`_
`MsiRecordSetInteger <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370371.aspx>`_
`MsiRecordClearData <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370364.aspx>`_
.. _msi-errors:
Errors
------
All wrappers around MSI functions raise :exc:`MSIError`; the string inside the
exception will contain more detail.
.. _cab:
CAB Objects
-----------
.. class:: CAB(name)
The class :class:`CAB` represents a CAB file. During MSI construction, files
will be added simultaneously to the ``Files`` table, and to a CAB file. Then,
when all files have been added, the CAB file can be written, then added to the
MSI file.
*name* is the name of the CAB file in the MSI file.
.. method:: append(full, file, logical)
Add the file with the pathname *full* to the CAB file, under the name
*logical*. If there is already a file named *logical*, a new file name is
created.
Return the index of the file in the CAB file, and the new name of the file
inside the CAB file.
.. method:: commit(database)
Generate a CAB file, add it as a stream to the MSI file, put it into the
``Media`` table, and remove the generated file from the disk.
.. _msi-directory:
Directory Objects
-----------------
.. class:: Directory(database, cab, basedir, physical, logical, default, [componentflags])
Create a new directory in the Directory table. There is a current component at
each point in time for the directory, which is either explicitly created through
:meth:`start_component`, or implicitly when files are added for the first time.
Files are added into the current component, and into the cab file. To create a
directory, a base directory object needs to be specified (can be ``None``), the
path to the physical directory, and a logical directory name. *default*
specifies the DefaultDir slot in the directory table. *componentflags* specifies
the default flags that new components get.
.. method:: start_component(component=None, feature=None, flags=None, keyfile=None, uuid=None)
Add an entry to the Component table, and make this component the current
component for this directory. If no component name is given, the directory
name is used. If no *feature* is given, the current feature is used. If no
*flags* are given, the directory's default flags are used. If no *keyfile*
is given, the KeyPath is left null in the Component table.
.. method:: add_file(file, src=None, version=None, language=None)
Add a file to the current component of the directory, starting a new one
if there is no current component. By default, the file name in the source
and the file table will be identical. If the *src* file is specified, it
is interpreted relative to the current directory. Optionally, a *version*
and a *language* can be specified for the entry in the File table.
.. method:: glob(pattern, exclude=None)
Add a list of files to the current component as specified in the glob
pattern. Individual files can be excluded in the *exclude* list.
.. method:: remove_pyc()
Remove ``.pyc`` files on uninstall.
.. seealso::
`Directory Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368295.aspx>`_
`File Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368596.aspx>`_
`Component Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368007.aspx>`_
`FeatureComponents Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368579.aspx>`_
.. _features:
Features
--------
.. class:: Feature(db, id, title, desc, display, level=1, parent=None, directory=None, attributes=0)
Add a new record to the ``Feature`` table, using the values *id*, *parent.id*,
*title*, *desc*, *display*, *level*, *directory*, and *attributes*. The
resulting feature object can be passed to the :meth:`start_component` method of
:class:`Directory`.
.. method:: set_current()
Make this feature the current feature of :mod:`msilib`. New components are
automatically added to the default feature, unless a feature is explicitly
specified.
.. seealso::
`Feature Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368585.aspx>`_
.. _msi-gui:
GUI classes
-----------
:mod:`msilib` provides several classes that wrap the GUI tables in an MSI
database. However, no standard user interface is provided.
.. class:: Control(dlg, name)
Base class of the dialog controls. *dlg* is the dialog object the control
belongs to, and *name* is the control's name.
.. method:: event(event, argument, condition=1, ordering=None)
Make an entry into the ``ControlEvent`` table for this control.
.. method:: mapping(event, attribute)
Make an entry into the ``EventMapping`` table for this control.
.. method:: condition(action, condition)
Make an entry into the ``ControlCondition`` table for this control.
.. class:: RadioButtonGroup(dlg, name, property)
Create a radio button control named *name*. *property* is the installer property
that gets set when a radio button is selected.
.. method:: add(name, x, y, width, height, text, value=None)
Add a radio button named *name* to the group, at the coordinates *x*, *y*,
*width*, *height*, and with the label *text*. If *value* is ``None``, it
defaults to *name*.
.. class:: Dialog(db, name, x, y, w, h, attr, title, first, default, cancel)
Return a new :class:`Dialog` object. An entry in the ``Dialog`` table is made,
with the specified coordinates, dialog attributes, title, name of the first,
default, and cancel controls.
.. method:: control(name, type, x, y, width, height, attributes, property, text, control_next, help)
Return a new :class:`Control` object. An entry in the ``Control`` table is
made with the specified parameters.
This is a generic method; for specific types, specialized methods are
provided.
.. method:: text(name, x, y, width, height, attributes, text)
Add and return a ``Text`` control.
.. method:: bitmap(name, x, y, width, height, text)
Add and return a ``Bitmap`` control.
.. method:: line(name, x, y, width, height)
Add and return a ``Line`` control.
.. method:: pushbutton(name, x, y, width, height, attributes, text, next_control)
Add and return a ``PushButton`` control.
.. method:: radiogroup(name, x, y, width, height, attributes, property, text, next_control)
Add and return a ``RadioButtonGroup`` control.
.. method:: checkbox(name, x, y, width, height, attributes, property, text, next_control)
Add and return a ``CheckBox`` control.
.. seealso::
`Dialog Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368286.aspx>`_
`Control Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368044.aspx>`_
`Control Types <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368039.aspx>`_
`ControlCondition Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368035.aspx>`_
`ControlEvent Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368037.aspx>`_
`EventMapping Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368559.aspx>`_
`RadioButton Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370962.aspx>`_
.. _msi-tables:
Precomputed tables
------------------
:mod:`msilib` provides a few subpackages that contain only schema and table
definitions. Currently, these definitions are based on MSI version 2.0.
.. data:: schema
This is the standard MSI schema for MSI 2.0, with the *tables* variable
providing a list of table definitions, and *_Validation_records* providing the
data for MSI validation.
.. data:: sequence
This module contains table contents for the standard sequence tables:
*AdminExecuteSequence*, *AdminUISequence*, *AdvtExecuteSequence*,
*InstallExecuteSequence*, and *InstallUISequence*.
.. data:: text
This module contains definitions for the UIText and ActionText tables, for the
standard installer actions.

View File

@ -15,6 +15,5 @@ backwards compatibility. They have been superseded by other modules.
chunk.rst
crypt.rst
imghdr.rst
msilib.rst
optparse.rst
uu.rst

View File

@ -161,7 +161,6 @@ Doc/library/logging.rst
Doc/library/lzma.rst
Doc/library/mailbox.rst
Doc/library/mmap.rst
Doc/library/msilib.rst
Doc/library/msvcrt.rst
Doc/library/multiprocessing.rst
Doc/library/multiprocessing.shared_memory.rst

View File

@ -1422,7 +1422,7 @@ complete list of changes, or look through the SVN logs for all the details.
(Contributed by Gregory K. Johnson. Funding was provided by Google's 2005
Summer of Code.)
* New module: the :mod:`msilib` module allows creating Microsoft Installer
* New module: the :mod:`!msilib` module allows creating Microsoft Installer
:file:`.msi` files and CAB files. Some support for reading the :file:`.msi`
database is also included. (Contributed by Martin von Löwis.)

View File

@ -3135,7 +3135,7 @@ Port-Specific Changes: Windows
registry reflection for 32-bit processes running on 64-bit systems.
(:issue:`1753245`)
* The :mod:`msilib` module's :class:`Record` object
* The :mod:`!msilib` module's :class:`Record` object
gained :meth:`GetInteger` and :meth:`GetString` methods that
return field values as an integer or a string.
(Contributed by Floris Bruynooghe; :issue:`2125`.)

View File

@ -1731,7 +1731,7 @@ Modules
slated for removal in Python 3.13:
+---------------------+---------------------+---------------------+---------------------+---------------------+
| :mod:`aifc` | :mod:`chunk` | :mod:`msilib` | :mod:`!pipes` | :mod:`!telnetlib` |
| :mod:`aifc` | :mod:`chunk` | :mod:`!msilib` | :mod:`!pipes` | :mod:`!telnetlib` |
+---------------------+---------------------+---------------------+---------------------+---------------------+
| :mod:`audioop` | :mod:`crypt` | :mod:`!nis` | :mod:`!sndhdr` | :mod:`uu` |
+---------------------+---------------------+---------------------+---------------------+---------------------+

View File

@ -894,7 +894,7 @@ Modules (see :pep:`594`):
* :mod:`crypt`
* :mod:`imghdr`
* :mod:`!mailcap`
* :mod:`msilib`
* :mod:`!msilib`
* :mod:`!nis`
* :mod:`!nntplib`
* :mod:`!ossaudiodev`

View File

@ -198,6 +198,9 @@ Removed
* :pep:`594`: Remove the :mod:`!xdrlib` module, deprecated in Python 3.11.
(Contributed by Victor Stinner in :gh:`104773`.)
* :pep:`594`: Remove the :mod:`!msilib` module, deprecated in Python 3.11.
(Contributed by Zachary Ware in :gh:`104773`.)
Porting to Python 3.13
======================

View File

@ -1133,7 +1133,7 @@ The MIME type of .bmp has been changed from ``'image/x-ms-bmp'`` to
msilib
------
The new :meth:`Database.Close() <msilib.Database.Close>` method can be used
The new :meth:`!Database.Close()` method can be used
to close the :abbr:`MSI` database.
(Contributed by Berker Peksag in :issue:`20486`.)

View File

@ -1,484 +0,0 @@
# Copyright (C) 2005 Martin v. Löwis
# Licensed to PSF under a Contributor Agreement.
from _msi import *
import fnmatch
import os
import re
import string
import sys
import warnings
warnings._deprecated(__name__, remove=(3, 13))
AMD64 = "AMD64" in sys.version
# Keep msilib.Win64 around to preserve backwards compatibility.
Win64 = AMD64
# Partially taken from Wine
datasizemask= 0x00ff
type_valid= 0x0100
type_localizable= 0x0200
typemask= 0x0c00
type_long= 0x0000
type_short= 0x0400
type_string= 0x0c00
type_binary= 0x0800
type_nullable= 0x1000
type_key= 0x2000
# XXX temporary, localizable?
knownbits = datasizemask | type_valid | type_localizable | \
typemask | type_nullable | type_key
class Table:
def __init__(self, name):
self.name = name
self.fields = []
def add_field(self, index, name, type):
self.fields.append((index,name,type))
def sql(self):
fields = []
keys = []
self.fields.sort()
fields = [None]*len(self.fields)
for index, name, type in self.fields:
index -= 1
unk = type & ~knownbits
if unk:
print("%s.%s unknown bits %x" % (self.name, name, unk))
size = type & datasizemask
dtype = type & typemask
if dtype == type_string:
if size:
tname="CHAR(%d)" % size
else:
tname="CHAR"
elif dtype == type_short:
assert size==2
tname = "SHORT"
elif dtype == type_long:
assert size==4
tname="LONG"
elif dtype == type_binary:
assert size==0
tname="OBJECT"
else:
tname="unknown"
print("%s.%sunknown integer type %d" % (self.name, name, size))
if type & type_nullable:
flags = ""
else:
flags = " NOT NULL"
if type & type_localizable:
flags += " LOCALIZABLE"
fields[index] = "`%s` %s%s" % (name, tname, flags)
if type & type_key:
keys.append("`%s`" % name)
fields = ", ".join(fields)
keys = ", ".join(keys)
return "CREATE TABLE %s (%s PRIMARY KEY %s)" % (self.name, fields, keys)
def create(self, db):
v = db.OpenView(self.sql())
v.Execute(None)
v.Close()
class _Unspecified:pass
def change_sequence(seq, action, seqno=_Unspecified, cond = _Unspecified):
"Change the sequence number of an action in a sequence list"
for i in range(len(seq)):
if seq[i][0] == action:
if cond is _Unspecified:
cond = seq[i][1]
if seqno is _Unspecified:
seqno = seq[i][2]
seq[i] = (action, cond, seqno)
return
raise ValueError("Action not found in sequence")
def add_data(db, table, values):
v = db.OpenView("SELECT * FROM `%s`" % table)
count = v.GetColumnInfo(MSICOLINFO_NAMES).GetFieldCount()
r = CreateRecord(count)
for value in values:
assert len(value) == count, value
for i in range(count):
field = value[i]
if isinstance(field, int):
r.SetInteger(i+1,field)
elif isinstance(field, str):
r.SetString(i+1,field)
elif field is None:
pass
elif isinstance(field, Binary):
r.SetStream(i+1, field.name)
else:
raise TypeError("Unsupported type %s" % field.__class__.__name__)
try:
v.Modify(MSIMODIFY_INSERT, r)
except Exception:
raise MSIError("Could not insert "+repr(values)+" into "+table)
r.ClearData()
v.Close()
def add_stream(db, name, path):
v = db.OpenView("INSERT INTO _Streams (Name, Data) VALUES ('%s', ?)" % name)
r = CreateRecord(1)
r.SetStream(1, path)
v.Execute(r)
v.Close()
def init_database(name, schema,
ProductName, ProductCode, ProductVersion,
Manufacturer):
try:
os.unlink(name)
except OSError:
pass
ProductCode = ProductCode.upper()
# Create the database
db = OpenDatabase(name, MSIDBOPEN_CREATE)
# Create the tables
for t in schema.tables:
t.create(db)
# Fill the validation table
add_data(db, "_Validation", schema._Validation_records)
# Initialize the summary information, allowing atmost 20 properties
si = db.GetSummaryInformation(20)
si.SetProperty(PID_TITLE, "Installation Database")
si.SetProperty(PID_SUBJECT, ProductName)
si.SetProperty(PID_AUTHOR, Manufacturer)
if AMD64:
si.SetProperty(PID_TEMPLATE, "x64;1033")
else:
si.SetProperty(PID_TEMPLATE, "Intel;1033")
si.SetProperty(PID_REVNUMBER, gen_uuid())
si.SetProperty(PID_WORDCOUNT, 2) # long file names, compressed, original media
si.SetProperty(PID_PAGECOUNT, 200)
si.SetProperty(PID_APPNAME, "Python MSI Library")
# XXX more properties
si.Persist()
add_data(db, "Property", [
("ProductName", ProductName),
("ProductCode", ProductCode),
("ProductVersion", ProductVersion),
("Manufacturer", Manufacturer),
("ProductLanguage", "1033")])
db.Commit()
return db
def add_tables(db, module):
for table in module.tables:
add_data(db, table, getattr(module, table))
def make_id(str):
identifier_chars = string.ascii_letters + string.digits + "._"
str = "".join([c if c in identifier_chars else "_" for c in str])
if str[0] in (string.digits + "."):
str = "_" + str
assert re.match("^[A-Za-z_][A-Za-z0-9_.]*$", str), "FILE"+str
return str
def gen_uuid():
return "{"+UuidCreate().upper()+"}"
class CAB:
def __init__(self, name):
self.name = name
self.files = []
self.filenames = set()
self.index = 0
def gen_id(self, file):
logical = _logical = make_id(file)
pos = 1
while logical in self.filenames:
logical = "%s.%d" % (_logical, pos)
pos += 1
self.filenames.add(logical)
return logical
def append(self, full, file, logical):
if os.path.isdir(full):
return
if not logical:
logical = self.gen_id(file)
self.index += 1
self.files.append((full, logical))
return self.index, logical
def commit(self, db):
from tempfile import mktemp
filename = mktemp()
FCICreate(filename, self.files)
add_data(db, "Media",
[(1, self.index, None, "#"+self.name, None, None)])
add_stream(db, self.name, filename)
os.unlink(filename)
db.Commit()
_directories = set()
class Directory:
def __init__(self, db, cab, basedir, physical, _logical, default, componentflags=None):
"""Create a new directory in the Directory table. There is a current component
at each point in time for the directory, which is either explicitly created
through start_component, or implicitly when files are added for the first
time. Files are added into the current component, and into the cab file.
To create a directory, a base directory object needs to be specified (can be
None), the path to the physical directory, and a logical directory name.
Default specifies the DefaultDir slot in the directory table. componentflags
specifies the default flags that new components get."""
index = 1
_logical = make_id(_logical)
logical = _logical
while logical in _directories:
logical = "%s%d" % (_logical, index)
index += 1
_directories.add(logical)
self.db = db
self.cab = cab
self.basedir = basedir
self.physical = physical
self.logical = logical
self.component = None
self.short_names = set()
self.ids = set()
self.keyfiles = {}
self.componentflags = componentflags
if basedir:
self.absolute = os.path.join(basedir.absolute, physical)
blogical = basedir.logical
else:
self.absolute = physical
blogical = None
add_data(db, "Directory", [(logical, blogical, default)])
def start_component(self, component = None, feature = None, flags = None, keyfile = None, uuid=None):
"""Add an entry to the Component table, and make this component the current for this
directory. If no component name is given, the directory name is used. If no feature
is given, the current feature is used. If no flags are given, the directory's default
flags are used. If no keyfile is given, the KeyPath is left null in the Component
table."""
if flags is None:
flags = self.componentflags
if uuid is None:
uuid = gen_uuid()
else:
uuid = uuid.upper()
if component is None:
component = self.logical
self.component = component
if AMD64:
flags |= 256
if keyfile:
keyid = self.cab.gen_id(keyfile)
self.keyfiles[keyfile] = keyid
else:
keyid = None
add_data(self.db, "Component",
[(component, uuid, self.logical, flags, None, keyid)])
if feature is None:
feature = current_feature
add_data(self.db, "FeatureComponents",
[(feature.id, component)])
def make_short(self, file):
oldfile = file
file = file.replace('+', '_')
file = ''.join(c for c in file if not c in r' "/\[]:;=,')
parts = file.split(".")
if len(parts) > 1:
prefix = "".join(parts[:-1]).upper()
suffix = parts[-1].upper()
if not prefix:
prefix = suffix
suffix = None
else:
prefix = file.upper()
suffix = None
if len(parts) < 3 and len(prefix) <= 8 and file == oldfile and (
not suffix or len(suffix) <= 3):
if suffix:
file = prefix+"."+suffix
else:
file = prefix
else:
file = None
if file is None or file in self.short_names:
prefix = prefix[:6]
if suffix:
suffix = suffix[:3]
pos = 1
while 1:
if suffix:
file = "%s~%d.%s" % (prefix, pos, suffix)
else:
file = "%s~%d" % (prefix, pos)
if file not in self.short_names: break
pos += 1
assert pos < 10000
if pos in (10, 100, 1000):
prefix = prefix[:-1]
self.short_names.add(file)
assert not re.search(r'[\?|><:/*"+,;=\[\]]', file) # restrictions on short names
return file
def add_file(self, file, src=None, version=None, language=None):
"""Add a file to the current component of the directory, starting a new one
if there is no current component. By default, the file name in the source
and the file table will be identical. If the src file is specified, it is
interpreted relative to the current directory. Optionally, a version and a
language can be specified for the entry in the File table."""
if not self.component:
self.start_component(self.logical, current_feature, 0)
if not src:
# Allow relative paths for file if src is not specified
src = file
file = os.path.basename(file)
absolute = os.path.join(self.absolute, src)
assert not re.search(r'[\?|><:/*]"', file) # restrictions on long names
if file in self.keyfiles:
logical = self.keyfiles[file]
else:
logical = None
sequence, logical = self.cab.append(absolute, file, logical)
assert logical not in self.ids
self.ids.add(logical)
short = self.make_short(file)
full = "%s|%s" % (short, file)
filesize = os.stat(absolute).st_size
# constants.msidbFileAttributesVital
# Compressed omitted, since it is the database default
# could add r/o, system, hidden
attributes = 512
add_data(self.db, "File",
[(logical, self.component, full, filesize, version,
language, attributes, sequence)])
#if not version:
# # Add hash if the file is not versioned
# filehash = FileHash(absolute, 0)
# add_data(self.db, "MsiFileHash",
# [(logical, 0, filehash.IntegerData(1),
# filehash.IntegerData(2), filehash.IntegerData(3),
# filehash.IntegerData(4))])
# Automatically remove .pyc files on uninstall (2)
# XXX: adding so many RemoveFile entries makes installer unbelievably
# slow. So instead, we have to use wildcard remove entries
if file.endswith(".py"):
add_data(self.db, "RemoveFile",
[(logical+"c", self.component, "%sC|%sc" % (short, file),
self.logical, 2),
(logical+"o", self.component, "%sO|%so" % (short, file),
self.logical, 2)])
return logical
def glob(self, pattern, exclude = None):
"""Add a list of files to the current component as specified in the
glob pattern. Individual files can be excluded in the exclude list."""
try:
files = os.listdir(self.absolute)
except OSError:
return []
if pattern[:1] != '.':
files = (f for f in files if f[0] != '.')
files = fnmatch.filter(files, pattern)
for f in files:
if exclude and f in exclude: continue
self.add_file(f)
return files
def remove_pyc(self):
"Remove .pyc files on uninstall"
add_data(self.db, "RemoveFile",
[(self.component+"c", self.component, "*.pyc", self.logical, 2)])
class Binary:
def __init__(self, fname):
self.name = fname
def __repr__(self):
return 'msilib.Binary(os.path.join(dirname,"%s"))' % self.name
class Feature:
def __init__(self, db, id, title, desc, display, level = 1,
parent=None, directory = None, attributes=0):
self.id = id
if parent:
parent = parent.id
add_data(db, "Feature",
[(id, parent, title, desc, display,
level, directory, attributes)])
def set_current(self):
global current_feature
current_feature = self
class Control:
def __init__(self, dlg, name):
self.dlg = dlg
self.name = name
def event(self, event, argument, condition = "1", ordering = None):
add_data(self.dlg.db, "ControlEvent",
[(self.dlg.name, self.name, event, argument,
condition, ordering)])
def mapping(self, event, attribute):
add_data(self.dlg.db, "EventMapping",
[(self.dlg.name, self.name, event, attribute)])
def condition(self, action, condition):
add_data(self.dlg.db, "ControlCondition",
[(self.dlg.name, self.name, action, condition)])
class RadioButtonGroup(Control):
def __init__(self, dlg, name, property):
self.dlg = dlg
self.name = name
self.property = property
self.index = 1
def add(self, name, x, y, w, h, text, value = None):
if value is None:
value = name
add_data(self.dlg.db, "RadioButton",
[(self.property, self.index, value,
x, y, w, h, text, None)])
self.index += 1
class Dialog:
def __init__(self, db, name, x, y, w, h, attr, title, first, default, cancel):
self.db = db
self.name = name
self.x, self.y, self.w, self.h = x,y,w,h
add_data(db, "Dialog", [(name, x,y,w,h,attr,title,first,default,cancel)])
def control(self, name, type, x, y, w, h, attr, prop, text, next, help):
add_data(self.db, "Control",
[(self.name, name, type, x, y, w, h, attr, prop, text, next, help)])
return Control(self, name)
def text(self, name, x, y, w, h, attr, text):
return self.control(name, "Text", x, y, w, h, attr, None,
text, None, None)
def bitmap(self, name, x, y, w, h, text):
return self.control(name, "Bitmap", x, y, w, h, 1, None, text, None, None)
def line(self, name, x, y, w, h):
return self.control(name, "Line", x, y, w, h, 1, None, None, None, None)
def pushbutton(self, name, x, y, w, h, attr, text, next):
return self.control(name, "PushButton", x, y, w, h, attr, None, text, next, None)
def radiogroup(self, name, x, y, w, h, attr, prop, text, next):
add_data(self.db, "Control",
[(self.name, name, "RadioButtonGroup",
x, y, w, h, attr, prop, text, next, None)])
return RadioButtonGroup(self, name, prop)
def checkbox(self, name, x, y, w, h, attr, prop, text, next):
return self.control(name, "CheckBox", x, y, w, h, attr, prop, text, next, None)

File diff suppressed because it is too large Load Diff

View File

@ -1,126 +0,0 @@
AdminExecuteSequence = [
('InstallInitialize', None, 1500),
('InstallFinalize', None, 6600),
('InstallFiles', None, 4000),
('InstallAdminPackage', None, 3900),
('FileCost', None, 900),
('CostInitialize', None, 800),
('CostFinalize', None, 1000),
('InstallValidate', None, 1400),
]
AdminUISequence = [
('FileCost', None, 900),
('CostInitialize', None, 800),
('CostFinalize', None, 1000),
('ExecuteAction', None, 1300),
('ExitDialog', None, -1),
('FatalError', None, -3),
('UserExit', None, -2),
]
AdvtExecuteSequence = [
('InstallInitialize', None, 1500),
('InstallFinalize', None, 6600),
('CostInitialize', None, 800),
('CostFinalize', None, 1000),
('InstallValidate', None, 1400),
('CreateShortcuts', None, 4500),
('MsiPublishAssemblies', None, 6250),
('PublishComponents', None, 6200),
('PublishFeatures', None, 6300),
('PublishProduct', None, 6400),
('RegisterClassInfo', None, 4600),
('RegisterExtensionInfo', None, 4700),
('RegisterMIMEInfo', None, 4900),
('RegisterProgIdInfo', None, 4800),
]
InstallExecuteSequence = [
('InstallInitialize', None, 1500),
('InstallFinalize', None, 6600),
('InstallFiles', None, 4000),
('FileCost', None, 900),
('CostInitialize', None, 800),
('CostFinalize', None, 1000),
('InstallValidate', None, 1400),
('CreateShortcuts', None, 4500),
('MsiPublishAssemblies', None, 6250),
('PublishComponents', None, 6200),
('PublishFeatures', None, 6300),
('PublishProduct', None, 6400),
('RegisterClassInfo', None, 4600),
('RegisterExtensionInfo', None, 4700),
('RegisterMIMEInfo', None, 4900),
('RegisterProgIdInfo', None, 4800),
('AllocateRegistrySpace', 'NOT Installed', 1550),
('AppSearch', None, 400),
('BindImage', None, 4300),
('CCPSearch', 'NOT Installed', 500),
('CreateFolders', None, 3700),
('DeleteServices', 'VersionNT', 2000),
('DuplicateFiles', None, 4210),
('FindRelatedProducts', None, 200),
('InstallODBC', None, 5400),
('InstallServices', 'VersionNT', 5800),
('IsolateComponents', None, 950),
('LaunchConditions', None, 100),
('MigrateFeatureStates', None, 1200),
('MoveFiles', None, 3800),
('PatchFiles', None, 4090),
('ProcessComponents', None, 1600),
('RegisterComPlus', None, 5700),
('RegisterFonts', None, 5300),
('RegisterProduct', None, 6100),
('RegisterTypeLibraries', None, 5500),
('RegisterUser', None, 6000),
('RemoveDuplicateFiles', None, 3400),
('RemoveEnvironmentStrings', None, 3300),
('RemoveExistingProducts', None, 6700),
('RemoveFiles', None, 3500),
('RemoveFolders', None, 3600),
('RemoveIniValues', None, 3100),
('RemoveODBC', None, 2400),
('RemoveRegistryValues', None, 2600),
('RemoveShortcuts', None, 3200),
('RMCCPSearch', 'NOT Installed', 600),
('SelfRegModules', None, 5600),
('SelfUnregModules', None, 2200),
('SetODBCFolders', None, 1100),
('StartServices', 'VersionNT', 5900),
('StopServices', 'VersionNT', 1900),
('MsiUnpublishAssemblies', None, 1750),
('UnpublishComponents', None, 1700),
('UnpublishFeatures', None, 1800),
('UnregisterClassInfo', None, 2700),
('UnregisterComPlus', None, 2100),
('UnregisterExtensionInfo', None, 2800),
('UnregisterFonts', None, 2500),
('UnregisterMIMEInfo', None, 3000),
('UnregisterProgIdInfo', None, 2900),
('UnregisterTypeLibraries', None, 2300),
('ValidateProductID', None, 700),
('WriteEnvironmentStrings', None, 5200),
('WriteIniValues', None, 5100),
('WriteRegistryValues', None, 5000),
]
InstallUISequence = [
('FileCost', None, 900),
('CostInitialize', None, 800),
('CostFinalize', None, 1000),
('ExecuteAction', None, 1300),
('ExitDialog', None, -1),
('FatalError', None, -3),
('UserExit', None, -2),
('AppSearch', None, 400),
('CCPSearch', 'NOT Installed', 500),
('FindRelatedProducts', None, 200),
('IsolateComponents', None, 950),
('LaunchConditions', None, 100),
('MigrateFeatureStates', None, 1200),
('RMCCPSearch', 'NOT Installed', 600),
('ValidateProductID', None, 700),
]
tables=['AdminExecuteSequence', 'AdminUISequence', 'AdvtExecuteSequence', 'InstallExecuteSequence', 'InstallUISequence']

View File

@ -1,129 +0,0 @@
import msilib,os;dirname=os.path.dirname(__file__)
ActionText = [
('InstallValidate', 'Validating install', None),
('InstallFiles', 'Copying new files', 'File: [1], Directory: [9], Size: [6]'),
('InstallAdminPackage', 'Copying network install files', 'File: [1], Directory: [9], Size: [6]'),
('FileCost', 'Computing space requirements', None),
('CostInitialize', 'Computing space requirements', None),
('CostFinalize', 'Computing space requirements', None),
('CreateShortcuts', 'Creating shortcuts', 'Shortcut: [1]'),
('PublishComponents', 'Publishing Qualified Components', 'Component ID: [1], Qualifier: [2]'),
('PublishFeatures', 'Publishing Product Features', 'Feature: [1]'),
('PublishProduct', 'Publishing product information', None),
('RegisterClassInfo', 'Registering Class servers', 'Class Id: [1]'),
('RegisterExtensionInfo', 'Registering extension servers', 'Extension: [1]'),
('RegisterMIMEInfo', 'Registering MIME info', 'MIME Content Type: [1], Extension: [2]'),
('RegisterProgIdInfo', 'Registering program identifiers', 'ProgId: [1]'),
('AllocateRegistrySpace', 'Allocating registry space', 'Free space: [1]'),
('AppSearch', 'Searching for installed applications', 'Property: [1], Signature: [2]'),
('BindImage', 'Binding executables', 'File: [1]'),
('CCPSearch', 'Searching for qualifying products', None),
('CreateFolders', 'Creating folders', 'Folder: [1]'),
('DeleteServices', 'Deleting services', 'Service: [1]'),
('DuplicateFiles', 'Creating duplicate files', 'File: [1], Directory: [9], Size: [6]'),
('FindRelatedProducts', 'Searching for related applications', 'Found application: [1]'),
('InstallODBC', 'Installing ODBC components', None),
('InstallServices', 'Installing new services', 'Service: [2]'),
('LaunchConditions', 'Evaluating launch conditions', None),
('MigrateFeatureStates', 'Migrating feature states from related applications', 'Application: [1]'),
('MoveFiles', 'Moving files', 'File: [1], Directory: [9], Size: [6]'),
('PatchFiles', 'Patching files', 'File: [1], Directory: [2], Size: [3]'),
('ProcessComponents', 'Updating component registration', None),
('RegisterComPlus', 'Registering COM+ Applications and Components', 'AppId: [1]{{, AppType: [2], Users: [3], RSN: [4]}}'),
('RegisterFonts', 'Registering fonts', 'Font: [1]'),
('RegisterProduct', 'Registering product', '[1]'),
('RegisterTypeLibraries', 'Registering type libraries', 'LibID: [1]'),
('RegisterUser', 'Registering user', '[1]'),
('RemoveDuplicateFiles', 'Removing duplicated files', 'File: [1], Directory: [9]'),
('RemoveEnvironmentStrings', 'Updating environment strings', 'Name: [1], Value: [2], Action [3]'),
('RemoveExistingProducts', 'Removing applications', 'Application: [1], Command line: [2]'),
('RemoveFiles', 'Removing files', 'File: [1], Directory: [9]'),
('RemoveFolders', 'Removing folders', 'Folder: [1]'),
('RemoveIniValues', 'Removing INI files entries', 'File: [1], Section: [2], Key: [3], Value: [4]'),
('RemoveODBC', 'Removing ODBC components', None),
('RemoveRegistryValues', 'Removing system registry values', 'Key: [1], Name: [2]'),
('RemoveShortcuts', 'Removing shortcuts', 'Shortcut: [1]'),
('RMCCPSearch', 'Searching for qualifying products', None),
('SelfRegModules', 'Registering modules', 'File: [1], Folder: [2]'),
('SelfUnregModules', 'Unregistering modules', 'File: [1], Folder: [2]'),
('SetODBCFolders', 'Initializing ODBC directories', None),
('StartServices', 'Starting services', 'Service: [1]'),
('StopServices', 'Stopping services', 'Service: [1]'),
('UnpublishComponents', 'Unpublishing Qualified Components', 'Component ID: [1], Qualifier: [2]'),
('UnpublishFeatures', 'Unpublishing Product Features', 'Feature: [1]'),
('UnregisterClassInfo', 'Unregister Class servers', 'Class Id: [1]'),
('UnregisterComPlus', 'Unregistering COM+ Applications and Components', 'AppId: [1]{{, AppType: [2]}}'),
('UnregisterExtensionInfo', 'Unregistering extension servers', 'Extension: [1]'),
('UnregisterFonts', 'Unregistering fonts', 'Font: [1]'),
('UnregisterMIMEInfo', 'Unregistering MIME info', 'MIME Content Type: [1], Extension: [2]'),
('UnregisterProgIdInfo', 'Unregistering program identifiers', 'ProgId: [1]'),
('UnregisterTypeLibraries', 'Unregistering type libraries', 'LibID: [1]'),
('WriteEnvironmentStrings', 'Updating environment strings', 'Name: [1], Value: [2], Action [3]'),
('WriteIniValues', 'Writing INI files values', 'File: [1], Section: [2], Key: [3], Value: [4]'),
('WriteRegistryValues', 'Writing system registry values', 'Key: [1], Name: [2], Value: [3]'),
('Advertise', 'Advertising application', None),
('GenerateScript', 'Generating script operations for action:', '[1]'),
('InstallSFPCatalogFile', 'Installing system catalog', 'File: [1], Dependencies: [2]'),
('MsiPublishAssemblies', 'Publishing assembly information', 'Application Context:[1], Assembly Name:[2]'),
('MsiUnpublishAssemblies', 'Unpublishing assembly information', 'Application Context:[1], Assembly Name:[2]'),
('Rollback', 'Rolling back action:', '[1]'),
('RollbackCleanup', 'Removing backup files', 'File: [1]'),
('UnmoveFiles', 'Removing moved files', 'File: [1], Directory: [9]'),
('UnpublishProduct', 'Unpublishing product information', None),
]
UIText = [
('AbsentPath', None),
('bytes', 'bytes'),
('GB', 'GB'),
('KB', 'KB'),
('MB', 'MB'),
('MenuAbsent', 'Entire feature will be unavailable'),
('MenuAdvertise', 'Feature will be installed when required'),
('MenuAllCD', 'Entire feature will be installed to run from CD'),
('MenuAllLocal', 'Entire feature will be installed on local hard drive'),
('MenuAllNetwork', 'Entire feature will be installed to run from network'),
('MenuCD', 'Will be installed to run from CD'),
('MenuLocal', 'Will be installed on local hard drive'),
('MenuNetwork', 'Will be installed to run from network'),
('ScriptInProgress', 'Gathering required information...'),
('SelAbsentAbsent', 'This feature will remain uninstalled'),
('SelAbsentAdvertise', 'This feature will be set to be installed when required'),
('SelAbsentCD', 'This feature will be installed to run from CD'),
('SelAbsentLocal', 'This feature will be installed on the local hard drive'),
('SelAbsentNetwork', 'This feature will be installed to run from the network'),
('SelAdvertiseAbsent', 'This feature will become unavailable'),
('SelAdvertiseAdvertise', 'Will be installed when required'),
('SelAdvertiseCD', 'This feature will be available to run from CD'),
('SelAdvertiseLocal', 'This feature will be installed on your local hard drive'),
('SelAdvertiseNetwork', 'This feature will be available to run from the network'),
('SelCDAbsent', "This feature will be uninstalled completely, you won't be able to run it from CD"),
('SelCDAdvertise', 'This feature will change from run from CD state to set to be installed when required'),
('SelCDCD', 'This feature will remain to be run from CD'),
('SelCDLocal', 'This feature will change from run from CD state to be installed on the local hard drive'),
('SelChildCostNeg', 'This feature frees up [1] on your hard drive.'),
('SelChildCostPos', 'This feature requires [1] on your hard drive.'),
('SelCostPending', 'Compiling cost for this feature...'),
('SelLocalAbsent', 'This feature will be completely removed'),
('SelLocalAdvertise', 'This feature will be removed from your local hard drive, but will be set to be installed when required'),
('SelLocalCD', 'This feature will be removed from your local hard drive, but will be still available to run from CD'),
('SelLocalLocal', 'This feature will remain on you local hard drive'),
('SelLocalNetwork', 'This feature will be removed from your local hard drive, but will be still available to run from the network'),
('SelNetworkAbsent', "This feature will be uninstalled completely, you won't be able to run it from the network"),
('SelNetworkAdvertise', 'This feature will change from run from network state to set to be installed when required'),
('SelNetworkLocal', 'This feature will change from run from network state to be installed on the local hard drive'),
('SelNetworkNetwork', 'This feature will remain to be run from the network'),
('SelParentCostNegNeg', 'This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.'),
('SelParentCostNegPos', 'This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.'),
('SelParentCostPosNeg', 'This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.'),
('SelParentCostPosPos', 'This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.'),
('TimeRemaining', 'Time remaining: {[1] minutes }{[2] seconds}'),
('VolumeCostAvailable', 'Available'),
('VolumeCostDifference', 'Difference'),
('VolumeCostRequired', 'Required'),
('VolumeCostSize', 'Disk Size'),
('VolumeCostVolume', 'Volume'),
]
tables=['ActionText', 'UIText']

View File

@ -1,166 +0,0 @@
""" Test suite for the code in msilib """
import os
import unittest
from test.support.import_helper import import_module
from test.support.os_helper import TESTFN, unlink
import warnings
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
msilib = import_module('msilib')
import msilib.schema
def init_database():
path = TESTFN + '.msi'
db = msilib.init_database(
path,
msilib.schema,
'Python Tests',
'product_code',
'1.0',
'PSF',
)
return db, path
class MsiDatabaseTestCase(unittest.TestCase):
def test_view_fetch_returns_none(self):
db, db_path = init_database()
properties = []
view = db.OpenView('SELECT Property, Value FROM Property')
view.Execute(None)
while True:
record = view.Fetch()
if record is None:
break
properties.append(record.GetString(1))
view.Close()
db.Close()
self.assertEqual(
properties,
[
'ProductName', 'ProductCode', 'ProductVersion',
'Manufacturer', 'ProductLanguage',
]
)
self.addCleanup(unlink, db_path)
def test_view_non_ascii(self):
db, db_path = init_database()
view = db.OpenView("SELECT 'ß-розпад' FROM Property")
view.Execute(None)
record = view.Fetch()
self.assertEqual(record.GetString(1), 'ß-розпад')
view.Close()
db.Close()
self.addCleanup(unlink, db_path)
def test_summaryinfo_getproperty_issue1104(self):
db, db_path = init_database()
try:
sum_info = db.GetSummaryInformation(99)
title = sum_info.GetProperty(msilib.PID_TITLE)
self.assertEqual(title, b"Installation Database")
sum_info.SetProperty(msilib.PID_TITLE, "a" * 999)
title = sum_info.GetProperty(msilib.PID_TITLE)
self.assertEqual(title, b"a" * 999)
sum_info.SetProperty(msilib.PID_TITLE, "a" * 1000)
title = sum_info.GetProperty(msilib.PID_TITLE)
self.assertEqual(title, b"a" * 1000)
sum_info.SetProperty(msilib.PID_TITLE, "a" * 1001)
title = sum_info.GetProperty(msilib.PID_TITLE)
self.assertEqual(title, b"a" * 1001)
finally:
db = None
sum_info = None
os.unlink(db_path)
def test_database_open_failed(self):
with self.assertRaises(msilib.MSIError) as cm:
msilib.OpenDatabase('non-existent.msi', msilib.MSIDBOPEN_READONLY)
self.assertEqual(str(cm.exception), 'open failed')
def test_database_create_failed(self):
db_path = os.path.join(TESTFN, 'test.msi')
with self.assertRaises(msilib.MSIError) as cm:
msilib.OpenDatabase(db_path, msilib.MSIDBOPEN_CREATE)
self.assertEqual(str(cm.exception), 'create failed')
def test_get_property_vt_empty(self):
db, db_path = init_database()
summary = db.GetSummaryInformation(0)
self.assertIsNone(summary.GetProperty(msilib.PID_SECURITY))
db.Close()
self.addCleanup(unlink, db_path)
def test_directory_start_component_keyfile(self):
db, db_path = init_database()
self.addCleanup(unlink, db_path)
self.addCleanup(db.Close)
self.addCleanup(msilib._directories.clear)
feature = msilib.Feature(db, 0, 'Feature', 'A feature', 'Python')
cab = msilib.CAB('CAB')
dir = msilib.Directory(db, cab, None, TESTFN, 'TARGETDIR',
'SourceDir', 0)
dir.start_component(None, feature, None, 'keyfile')
def test_getproperty_uninitialized_var(self):
db, db_path = init_database()
self.addCleanup(unlink, db_path)
self.addCleanup(db.Close)
si = db.GetSummaryInformation(0)
with self.assertRaises(msilib.MSIError):
si.GetProperty(-1)
def test_FCICreate(self):
filepath = TESTFN + '.txt'
cabpath = TESTFN + '.cab'
self.addCleanup(unlink, filepath)
with open(filepath, 'wb'):
pass
self.addCleanup(unlink, cabpath)
msilib.FCICreate(cabpath, [(filepath, 'test.txt')])
self.assertTrue(os.path.isfile(cabpath))
class Test_make_id(unittest.TestCase):
#http://msdn.microsoft.com/en-us/library/aa369212(v=vs.85).aspx
"""The Identifier data type is a text string. Identifiers may contain the
ASCII characters A-Z (a-z), digits, underscores (_), or periods (.).
However, every identifier must begin with either a letter or an
underscore.
"""
def test_is_no_change_required(self):
self.assertEqual(
msilib.make_id("short"), "short")
self.assertEqual(
msilib.make_id("nochangerequired"), "nochangerequired")
self.assertEqual(
msilib.make_id("one.dot"), "one.dot")
self.assertEqual(
msilib.make_id("_"), "_")
self.assertEqual(
msilib.make_id("a"), "a")
#self.assertEqual(
# msilib.make_id(""), "")
def test_invalid_first_char(self):
self.assertEqual(
msilib.make_id("9.short"), "_9.short")
self.assertEqual(
msilib.make_id(".short"), "_.short")
def test_invalid_any_char(self):
self.assertEqual(
msilib.make_id(".s\x82ort"), "_.s_ort")
self.assertEqual(
msilib.make_id(".s\x82o?*+rt"), "_.s_o___rt")
if __name__ == '__main__':
unittest.main()

View File

@ -2986,7 +2986,7 @@ Update Windows release to include SQLite 3.32.3.
.. nonce: jpZzzh
.. section: Windows
:mod:`msilib` now supports creating CAB files with non-ASCII file path and
:mod:`!msilib` now supports creating CAB files with non-ASCII file path and
adding files with non-ASCII file path to them.
..
@ -2996,9 +2996,9 @@ adding files with non-ASCII file path to them.
.. nonce: gaQc3C
.. section: Windows
Fixed support of non-ASCII names in functions :func:`msilib.OpenDatabase`
and :func:`msilib.init_database` and non-ASCII SQL in method
:meth:`msilib.Database.OpenView`.
Fixed support of non-ASCII names in functions :func:`!msilib.OpenDatabase`
and :func:`!msilib.init_database` and non-ASCII SQL in method
:meth:`!msilib.Database.OpenView`.
..

View File

@ -5400,7 +5400,7 @@ Update libffi to 3.4.3
.. nonce: kV4K_1
.. section: Windows
Fixes a potential buffer overrun in :mod:`msilib`.
Fixes a potential buffer overrun in :mod:`!msilib`.
..

View File

@ -294,7 +294,7 @@ by Nir Soffer.
.. nonce: Nj3A0x
.. section: Library
Make :meth:`msilib.SummaryInformation.GetProperty` return ``None`` when the
Make :meth:`!msilib.SummaryInformation.GetProperty` return ``None`` when the
value of property is ``VT_EMPTY``. Initial patch by Mark Mc Mahon.
..
@ -316,7 +316,7 @@ Initial patch by Robin Wellner.
.. nonce: xWT9k0
.. section: Library
:func:`msilib.OpenDatabase` now raises a better exception message when it
:func:`!msilib.OpenDatabase` now raises a better exception message when it
couldn't open or create an MSI file. Initial patch by William Tisäter.
..

View File

@ -350,7 +350,7 @@ the left most segment of hostname in second argument of
.. nonce: Nj3A0x
.. section: Library
Make :meth:`msilib.SummaryInformation.GetProperty` return ``None`` when the
Make :meth:`!msilib.SummaryInformation.GetProperty` return ``None`` when the
value of property is ``VT_EMPTY``. Initial patch by Mark Mc Mahon.
..
@ -396,7 +396,7 @@ Initial patch by Robin Wellner.
.. nonce: xWT9k0
.. section: Library
:func:`msilib.OpenDatabase` now raises a better exception message when it
:func:`!msilib.OpenDatabase` now raises a better exception message when it
couldn't open or create an MSI file. Initial patch by William Tisäter.
..

View File

@ -509,7 +509,7 @@ Add SSLContext.num_tickets to control the number of TLSv1.3 session tickets.
.. nonce: nobzc9
.. section: Library
Fix the error handling in :meth:`msilib.SummaryInformation.GetProperty`.
Fix the error handling in :meth:`!msilib.SummaryInformation.GetProperty`.
Patch by Zackery Spytz.
..
@ -538,7 +538,7 @@ module.
.. nonce: TQFOR4
.. section: Library
:meth:`msilib.Directory.start_component()` no longer fails if *keyfile* is
:meth:`!msilib.Directory.start_component()` no longer fails if *keyfile* is
not ``None``.
..

View File

@ -0,0 +1 @@
:pep:`594`: Removed the :mod:`!msilib` package, deprecated in Python 3.11.

1312
PC/_msi.c

File diff suppressed because it is too large Load Diff

698
PC/clinic/_msi.c.h generated
View File

@ -1,698 +0,0 @@
/*[clinic input]
preserve
[clinic start generated code]*/
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
PyDoc_STRVAR(_msi_UuidCreate__doc__,
"UuidCreate($module, /)\n"
"--\n"
"\n"
"Return the string representation of a new unique identifier.");
#define _MSI_UUIDCREATE_METHODDEF \
{"UuidCreate", (PyCFunction)_msi_UuidCreate, METH_NOARGS, _msi_UuidCreate__doc__},
static PyObject *
_msi_UuidCreate_impl(PyObject *module);
static PyObject *
_msi_UuidCreate(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return _msi_UuidCreate_impl(module);
}
PyDoc_STRVAR(_msi_FCICreate__doc__,
"FCICreate($module, cabname, files, /)\n"
"--\n"
"\n"
"Create a new CAB file.\n"
"\n"
" cabname\n"
" the name of the CAB file\n"
" files\n"
" a list of tuples, each containing the name of the file on disk,\n"
" and the name of the file inside the CAB file");
#define _MSI_FCICREATE_METHODDEF \
{"FCICreate", _PyCFunction_CAST(_msi_FCICreate), METH_FASTCALL, _msi_FCICreate__doc__},
static PyObject *
_msi_FCICreate_impl(PyObject *module, const char *cabname, PyObject *files);
static PyObject *
_msi_FCICreate(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
const char *cabname;
PyObject *files;
if (!_PyArg_CheckPositional("FCICreate", nargs, 2, 2)) {
goto exit;
}
if (!PyUnicode_Check(args[0])) {
_PyArg_BadArgument("FCICreate", "argument 1", "str", args[0]);
goto exit;
}
Py_ssize_t cabname_length;
cabname = PyUnicode_AsUTF8AndSize(args[0], &cabname_length);
if (cabname == NULL) {
goto exit;
}
if (strlen(cabname) != (size_t)cabname_length) {
PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
files = args[1];
return_value = _msi_FCICreate_impl(module, cabname, files);
exit:
return return_value;
}
PyDoc_STRVAR(_msi_Database_Close__doc__,
"Close($self, /)\n"
"--\n"
"\n"
"Close the database object.");
#define _MSI_DATABASE_CLOSE_METHODDEF \
{"Close", (PyCFunction)_msi_Database_Close, METH_NOARGS, _msi_Database_Close__doc__},
static PyObject *
_msi_Database_Close_impl(msiobj *self);
static PyObject *
_msi_Database_Close(msiobj *self, PyObject *Py_UNUSED(ignored))
{
return _msi_Database_Close_impl(self);
}
PyDoc_STRVAR(_msi_Record_GetFieldCount__doc__,
"GetFieldCount($self, /)\n"
"--\n"
"\n"
"Return the number of fields of the record.");
#define _MSI_RECORD_GETFIELDCOUNT_METHODDEF \
{"GetFieldCount", (PyCFunction)_msi_Record_GetFieldCount, METH_NOARGS, _msi_Record_GetFieldCount__doc__},
static PyObject *
_msi_Record_GetFieldCount_impl(msiobj *self);
static PyObject *
_msi_Record_GetFieldCount(msiobj *self, PyObject *Py_UNUSED(ignored))
{
return _msi_Record_GetFieldCount_impl(self);
}
PyDoc_STRVAR(_msi_Record_GetInteger__doc__,
"GetInteger($self, field, /)\n"
"--\n"
"\n"
"Return the value of field as an integer where possible.");
#define _MSI_RECORD_GETINTEGER_METHODDEF \
{"GetInteger", (PyCFunction)_msi_Record_GetInteger, METH_O, _msi_Record_GetInteger__doc__},
static PyObject *
_msi_Record_GetInteger_impl(msiobj *self, unsigned int field);
static PyObject *
_msi_Record_GetInteger(msiobj *self, PyObject *arg)
{
PyObject *return_value = NULL;
unsigned int field;
field = (unsigned int)PyLong_AsUnsignedLongMask(arg);
if (field == (unsigned int)-1 && PyErr_Occurred()) {
goto exit;
}
return_value = _msi_Record_GetInteger_impl(self, field);
exit:
return return_value;
}
PyDoc_STRVAR(_msi_Record_GetString__doc__,
"GetString($self, field, /)\n"
"--\n"
"\n"
"Return the value of field as a string where possible.");
#define _MSI_RECORD_GETSTRING_METHODDEF \
{"GetString", (PyCFunction)_msi_Record_GetString, METH_O, _msi_Record_GetString__doc__},
static PyObject *
_msi_Record_GetString_impl(msiobj *self, unsigned int field);
static PyObject *
_msi_Record_GetString(msiobj *self, PyObject *arg)
{
PyObject *return_value = NULL;
unsigned int field;
field = (unsigned int)PyLong_AsUnsignedLongMask(arg);
if (field == (unsigned int)-1 && PyErr_Occurred()) {
goto exit;
}
return_value = _msi_Record_GetString_impl(self, field);
exit:
return return_value;
}
PyDoc_STRVAR(_msi_Record_ClearData__doc__,
"ClearData($self, /)\n"
"--\n"
"\n"
"Set all fields of the record to 0.");
#define _MSI_RECORD_CLEARDATA_METHODDEF \
{"ClearData", (PyCFunction)_msi_Record_ClearData, METH_NOARGS, _msi_Record_ClearData__doc__},
static PyObject *
_msi_Record_ClearData_impl(msiobj *self);
static PyObject *
_msi_Record_ClearData(msiobj *self, PyObject *Py_UNUSED(ignored))
{
return _msi_Record_ClearData_impl(self);
}
PyDoc_STRVAR(_msi_Record_SetString__doc__,
"SetString($self, field, value, /)\n"
"--\n"
"\n"
"Set field to a string value.");
#define _MSI_RECORD_SETSTRING_METHODDEF \
{"SetString", _PyCFunction_CAST(_msi_Record_SetString), METH_FASTCALL, _msi_Record_SetString__doc__},
static PyObject *
_msi_Record_SetString_impl(msiobj *self, int field, const Py_UNICODE *value);
static PyObject *
_msi_Record_SetString(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
int field;
const Py_UNICODE *value = NULL;
if (!_PyArg_CheckPositional("SetString", nargs, 2, 2)) {
goto exit;
}
field = _PyLong_AsInt(args[0]);
if (field == -1 && PyErr_Occurred()) {
goto exit;
}
if (!PyUnicode_Check(args[1])) {
_PyArg_BadArgument("SetString", "argument 2", "str", args[1]);
goto exit;
}
value = PyUnicode_AsWideCharString(args[1], NULL);
if (value == NULL) {
goto exit;
}
return_value = _msi_Record_SetString_impl(self, field, value);
exit:
/* Cleanup for value */
PyMem_Free((void *)value);
return return_value;
}
PyDoc_STRVAR(_msi_Record_SetStream__doc__,
"SetStream($self, field, value, /)\n"
"--\n"
"\n"
"Set field to the contents of the file named value.");
#define _MSI_RECORD_SETSTREAM_METHODDEF \
{"SetStream", _PyCFunction_CAST(_msi_Record_SetStream), METH_FASTCALL, _msi_Record_SetStream__doc__},
static PyObject *
_msi_Record_SetStream_impl(msiobj *self, int field, const Py_UNICODE *value);
static PyObject *
_msi_Record_SetStream(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
int field;
const Py_UNICODE *value = NULL;
if (!_PyArg_CheckPositional("SetStream", nargs, 2, 2)) {
goto exit;
}
field = _PyLong_AsInt(args[0]);
if (field == -1 && PyErr_Occurred()) {
goto exit;
}
if (!PyUnicode_Check(args[1])) {
_PyArg_BadArgument("SetStream", "argument 2", "str", args[1]);
goto exit;
}
value = PyUnicode_AsWideCharString(args[1], NULL);
if (value == NULL) {
goto exit;
}
return_value = _msi_Record_SetStream_impl(self, field, value);
exit:
/* Cleanup for value */
PyMem_Free((void *)value);
return return_value;
}
PyDoc_STRVAR(_msi_Record_SetInteger__doc__,
"SetInteger($self, field, value, /)\n"
"--\n"
"\n"
"Set field to an integer value.");
#define _MSI_RECORD_SETINTEGER_METHODDEF \
{"SetInteger", _PyCFunction_CAST(_msi_Record_SetInteger), METH_FASTCALL, _msi_Record_SetInteger__doc__},
static PyObject *
_msi_Record_SetInteger_impl(msiobj *self, int field, int value);
static PyObject *
_msi_Record_SetInteger(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
int field;
int value;
if (!_PyArg_CheckPositional("SetInteger", nargs, 2, 2)) {
goto exit;
}
field = _PyLong_AsInt(args[0]);
if (field == -1 && PyErr_Occurred()) {
goto exit;
}
value = _PyLong_AsInt(args[1]);
if (value == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = _msi_Record_SetInteger_impl(self, field, value);
exit:
return return_value;
}
PyDoc_STRVAR(_msi_SummaryInformation_GetProperty__doc__,
"GetProperty($self, field, /)\n"
"--\n"
"\n"
"Return a property of the summary.\n"
"\n"
" field\n"
" the name of the property, one of the PID_* constants");
#define _MSI_SUMMARYINFORMATION_GETPROPERTY_METHODDEF \
{"GetProperty", (PyCFunction)_msi_SummaryInformation_GetProperty, METH_O, _msi_SummaryInformation_GetProperty__doc__},
static PyObject *
_msi_SummaryInformation_GetProperty_impl(msiobj *self, int field);
static PyObject *
_msi_SummaryInformation_GetProperty(msiobj *self, PyObject *arg)
{
PyObject *return_value = NULL;
int field;
field = _PyLong_AsInt(arg);
if (field == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = _msi_SummaryInformation_GetProperty_impl(self, field);
exit:
return return_value;
}
PyDoc_STRVAR(_msi_SummaryInformation_GetPropertyCount__doc__,
"GetPropertyCount($self, /)\n"
"--\n"
"\n"
"Return the number of summary properties.");
#define _MSI_SUMMARYINFORMATION_GETPROPERTYCOUNT_METHODDEF \
{"GetPropertyCount", (PyCFunction)_msi_SummaryInformation_GetPropertyCount, METH_NOARGS, _msi_SummaryInformation_GetPropertyCount__doc__},
static PyObject *
_msi_SummaryInformation_GetPropertyCount_impl(msiobj *self);
static PyObject *
_msi_SummaryInformation_GetPropertyCount(msiobj *self, PyObject *Py_UNUSED(ignored))
{
return _msi_SummaryInformation_GetPropertyCount_impl(self);
}
PyDoc_STRVAR(_msi_SummaryInformation_SetProperty__doc__,
"SetProperty($self, field, value, /)\n"
"--\n"
"\n"
"Set a property.\n"
"\n"
" field\n"
" the name of the property, one of the PID_* constants\n"
" value\n"
" the new value of the property (integer or string)");
#define _MSI_SUMMARYINFORMATION_SETPROPERTY_METHODDEF \
{"SetProperty", _PyCFunction_CAST(_msi_SummaryInformation_SetProperty), METH_FASTCALL, _msi_SummaryInformation_SetProperty__doc__},
static PyObject *
_msi_SummaryInformation_SetProperty_impl(msiobj *self, int field,
PyObject *data);
static PyObject *
_msi_SummaryInformation_SetProperty(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
int field;
PyObject *data;
if (!_PyArg_CheckPositional("SetProperty", nargs, 2, 2)) {
goto exit;
}
field = _PyLong_AsInt(args[0]);
if (field == -1 && PyErr_Occurred()) {
goto exit;
}
data = args[1];
return_value = _msi_SummaryInformation_SetProperty_impl(self, field, data);
exit:
return return_value;
}
PyDoc_STRVAR(_msi_SummaryInformation_Persist__doc__,
"Persist($self, /)\n"
"--\n"
"\n"
"Write the modified properties to the summary information stream.");
#define _MSI_SUMMARYINFORMATION_PERSIST_METHODDEF \
{"Persist", (PyCFunction)_msi_SummaryInformation_Persist, METH_NOARGS, _msi_SummaryInformation_Persist__doc__},
static PyObject *
_msi_SummaryInformation_Persist_impl(msiobj *self);
static PyObject *
_msi_SummaryInformation_Persist(msiobj *self, PyObject *Py_UNUSED(ignored))
{
return _msi_SummaryInformation_Persist_impl(self);
}
PyDoc_STRVAR(_msi_View_Execute__doc__,
"Execute($self, params, /)\n"
"--\n"
"\n"
"Execute the SQL query of the view.\n"
"\n"
" params\n"
" a record describing actual values of the parameter tokens\n"
" in the query or None");
#define _MSI_VIEW_EXECUTE_METHODDEF \
{"Execute", (PyCFunction)_msi_View_Execute, METH_O, _msi_View_Execute__doc__},
PyDoc_STRVAR(_msi_View_Fetch__doc__,
"Fetch($self, /)\n"
"--\n"
"\n"
"Return a result record of the query.");
#define _MSI_VIEW_FETCH_METHODDEF \
{"Fetch", (PyCFunction)_msi_View_Fetch, METH_NOARGS, _msi_View_Fetch__doc__},
static PyObject *
_msi_View_Fetch_impl(msiobj *self);
static PyObject *
_msi_View_Fetch(msiobj *self, PyObject *Py_UNUSED(ignored))
{
return _msi_View_Fetch_impl(self);
}
PyDoc_STRVAR(_msi_View_GetColumnInfo__doc__,
"GetColumnInfo($self, kind, /)\n"
"--\n"
"\n"
"Return a record describing the columns of the view.\n"
"\n"
" kind\n"
" MSICOLINFO_NAMES or MSICOLINFO_TYPES");
#define _MSI_VIEW_GETCOLUMNINFO_METHODDEF \
{"GetColumnInfo", (PyCFunction)_msi_View_GetColumnInfo, METH_O, _msi_View_GetColumnInfo__doc__},
static PyObject *
_msi_View_GetColumnInfo_impl(msiobj *self, int kind);
static PyObject *
_msi_View_GetColumnInfo(msiobj *self, PyObject *arg)
{
PyObject *return_value = NULL;
int kind;
kind = _PyLong_AsInt(arg);
if (kind == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = _msi_View_GetColumnInfo_impl(self, kind);
exit:
return return_value;
}
PyDoc_STRVAR(_msi_View_Modify__doc__,
"Modify($self, kind, data, /)\n"
"--\n"
"\n"
"Modify the view.\n"
"\n"
" kind\n"
" one of the MSIMODIFY_* constants\n"
" data\n"
" a record describing the new data");
#define _MSI_VIEW_MODIFY_METHODDEF \
{"Modify", _PyCFunction_CAST(_msi_View_Modify), METH_FASTCALL, _msi_View_Modify__doc__},
static PyObject *
_msi_View_Modify_impl(msiobj *self, int kind, PyObject *data);
static PyObject *
_msi_View_Modify(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
int kind;
PyObject *data;
if (!_PyArg_CheckPositional("Modify", nargs, 2, 2)) {
goto exit;
}
kind = _PyLong_AsInt(args[0]);
if (kind == -1 && PyErr_Occurred()) {
goto exit;
}
data = args[1];
return_value = _msi_View_Modify_impl(self, kind, data);
exit:
return return_value;
}
PyDoc_STRVAR(_msi_View_Close__doc__,
"Close($self, /)\n"
"--\n"
"\n"
"Close the view.");
#define _MSI_VIEW_CLOSE_METHODDEF \
{"Close", (PyCFunction)_msi_View_Close, METH_NOARGS, _msi_View_Close__doc__},
static PyObject *
_msi_View_Close_impl(msiobj *self);
static PyObject *
_msi_View_Close(msiobj *self, PyObject *Py_UNUSED(ignored))
{
return _msi_View_Close_impl(self);
}
PyDoc_STRVAR(_msi_Database_OpenView__doc__,
"OpenView($self, sql, /)\n"
"--\n"
"\n"
"Return a view object.\n"
"\n"
" sql\n"
" the SQL statement to execute");
#define _MSI_DATABASE_OPENVIEW_METHODDEF \
{"OpenView", (PyCFunction)_msi_Database_OpenView, METH_O, _msi_Database_OpenView__doc__},
static PyObject *
_msi_Database_OpenView_impl(msiobj *self, const Py_UNICODE *sql);
static PyObject *
_msi_Database_OpenView(msiobj *self, PyObject *arg)
{
PyObject *return_value = NULL;
const Py_UNICODE *sql = NULL;
if (!PyUnicode_Check(arg)) {
_PyArg_BadArgument("OpenView", "argument", "str", arg);
goto exit;
}
sql = PyUnicode_AsWideCharString(arg, NULL);
if (sql == NULL) {
goto exit;
}
return_value = _msi_Database_OpenView_impl(self, sql);
exit:
/* Cleanup for sql */
PyMem_Free((void *)sql);
return return_value;
}
PyDoc_STRVAR(_msi_Database_Commit__doc__,
"Commit($self, /)\n"
"--\n"
"\n"
"Commit the changes pending in the current transaction.");
#define _MSI_DATABASE_COMMIT_METHODDEF \
{"Commit", (PyCFunction)_msi_Database_Commit, METH_NOARGS, _msi_Database_Commit__doc__},
static PyObject *
_msi_Database_Commit_impl(msiobj *self);
static PyObject *
_msi_Database_Commit(msiobj *self, PyObject *Py_UNUSED(ignored))
{
return _msi_Database_Commit_impl(self);
}
PyDoc_STRVAR(_msi_Database_GetSummaryInformation__doc__,
"GetSummaryInformation($self, count, /)\n"
"--\n"
"\n"
"Return a new summary information object.\n"
"\n"
" count\n"
" the maximum number of updated values");
#define _MSI_DATABASE_GETSUMMARYINFORMATION_METHODDEF \
{"GetSummaryInformation", (PyCFunction)_msi_Database_GetSummaryInformation, METH_O, _msi_Database_GetSummaryInformation__doc__},
static PyObject *
_msi_Database_GetSummaryInformation_impl(msiobj *self, int count);
static PyObject *
_msi_Database_GetSummaryInformation(msiobj *self, PyObject *arg)
{
PyObject *return_value = NULL;
int count;
count = _PyLong_AsInt(arg);
if (count == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = _msi_Database_GetSummaryInformation_impl(self, count);
exit:
return return_value;
}
PyDoc_STRVAR(_msi_OpenDatabase__doc__,
"OpenDatabase($module, path, persist, /)\n"
"--\n"
"\n"
"Return a new database object.\n"
"\n"
" path\n"
" the file name of the MSI file\n"
" persist\n"
" the persistence mode");
#define _MSI_OPENDATABASE_METHODDEF \
{"OpenDatabase", _PyCFunction_CAST(_msi_OpenDatabase), METH_FASTCALL, _msi_OpenDatabase__doc__},
static PyObject *
_msi_OpenDatabase_impl(PyObject *module, const Py_UNICODE *path, int persist);
static PyObject *
_msi_OpenDatabase(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
const Py_UNICODE *path = NULL;
int persist;
if (!_PyArg_CheckPositional("OpenDatabase", nargs, 2, 2)) {
goto exit;
}
if (!PyUnicode_Check(args[0])) {
_PyArg_BadArgument("OpenDatabase", "argument 1", "str", args[0]);
goto exit;
}
path = PyUnicode_AsWideCharString(args[0], NULL);
if (path == NULL) {
goto exit;
}
persist = _PyLong_AsInt(args[1]);
if (persist == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = _msi_OpenDatabase_impl(module, path, persist);
exit:
/* Cleanup for path */
PyMem_Free((void *)path);
return return_value;
}
PyDoc_STRVAR(_msi_CreateRecord__doc__,
"CreateRecord($module, count, /)\n"
"--\n"
"\n"
"Return a new record object.\n"
"\n"
" count\n"
" the number of fields of the record");
#define _MSI_CREATERECORD_METHODDEF \
{"CreateRecord", (PyCFunction)_msi_CreateRecord, METH_O, _msi_CreateRecord__doc__},
static PyObject *
_msi_CreateRecord_impl(PyObject *module, int count);
static PyObject *
_msi_CreateRecord(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
int count;
count = _PyLong_AsInt(arg);
if (count == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = _msi_CreateRecord_impl(module, count);
exit:
return return_value;
}
/*[clinic end generated code: output=7d083c61679eed83 input=a9049054013a1b77]*/

View File

@ -1,115 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|ARM">
<Configuration>PGInstrument</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|ARM64">
<Configuration>PGInstrument</Configuration>
<Platform>ARM4</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|Win32">
<Configuration>PGInstrument</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|x64">
<Configuration>PGInstrument</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|ARM">
<Configuration>PGUpdate</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|ARM64">
<Configuration>PGUpdate</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|Win32">
<Configuration>PGUpdate</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|x64">
<Configuration>PGUpdate</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{31FFC478-7B4A-43E8-9954-8D03E2187E9C}</ProjectGuid>
<RootNamespace>_msi</RootNamespace>
<Keyword>Win32Proj</Keyword>
<SupportPGO>false</SupportPGO>
</PropertyGroup>
<Import Project="python.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<TargetExt>.pyd</TargetExt>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="pyproject.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>cabinet.lib;msi.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\PC\_msi.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\python_nt.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{bdef7710-e433-4ac0-84e0-14f34454bd3e}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{8513f324-7c13-4657-b463-5d686a8a5371}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\PC\_msi.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\python_nt.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -64,7 +64,7 @@
<!-- pyshellext.dll -->
<Projects Include="pyshellext.vcxproj" />
<!-- Extension modules -->
<ExtensionModules Include="_asyncio;_zoneinfo;_decimal;_elementtree;_msi;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound;_uuid;_wmi" />
<ExtensionModules Include="_asyncio;_zoneinfo;_decimal;_elementtree;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound;_uuid;_wmi" />
<ExtensionModules Include="_ctypes" Condition="$(IncludeCTypes)" />
<!-- Extension modules that require external sources -->
<ExternalModules Include="_bz2;_lzma;_sqlite3" />

View File

@ -68,8 +68,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes_test", "_ctypes_tes
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_elementtree", "_elementtree.vcxproj", "{17E1E049-C309-4D79-843F-AE483C264AEA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_msi", "_msi.vcxproj", "{31FFC478-7B4A-43E8-9954-8D03E2187E9C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_socket", "_socket.vcxproj", "{86937F53-C189-40EF-8CE8-8759D8E7D480}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_sqlite3", "_sqlite3.vcxproj", "{13CECB97-4119-4316-9D42-8534019A5A44}"

View File

@ -138,7 +138,6 @@ _zoneinfo
_decimal
_elementtree
_hashlib
_msi
_multiprocessing
_overlapped
_socket

View File

@ -45,7 +45,6 @@ static const char* _Py_stdlib_module_names[] = {
"_lzma",
"_markupbase",
"_md5",
"_msi",
"_multibytecodec",
"_multiprocessing",
"_opcode",
@ -180,7 +179,6 @@ static const char* _Py_stdlib_module_names[] = {
"mimetypes",
"mmap",
"modulefinder",
"msilib",
"msvcrt",
"multiprocessing",
"netrc",

View File

@ -50,7 +50,6 @@ CORE_MODULES = {
# Windows-only modules
WINDOWS_MODULES = {
"_msi",
"_overlapped",
"_testconsole",
"_winapi",

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define exts=pyexpat;select;unicodedata;winsound;_bz2;_elementtree;_socket;_ssl;_msi;_ctypes;_hashlib;_multiprocessing;_lzma;_decimal;_overlapped;_sqlite3;_asyncio;_queue;_uuid;_wmi;_zoneinfo ?>
<?define exts=pyexpat;select;unicodedata;winsound;_bz2;_elementtree;_socket;_ssl;_ctypes;_hashlib;_multiprocessing;_lzma;_decimal;_overlapped;_sqlite3;_asyncio;_queue;_uuid;_wmi;_zoneinfo ?>
<Fragment>
<DirectoryRef Id="Lib_venv_scripts_nt" />

View File

@ -56,7 +56,6 @@ OMIT_FILES = (
"concurrent/futures/thread.py",
# Misc unused or large files
"pydoc_data/",
"msilib/",
)
# Synchronous network I/O and protocols are not supported; for example,