text:
import msilib, schema, sequence, os, glob, time, re, shutil, zipfile
from msilib import Feature, CAB, Directory, Dialog, Binary, add_data
import uisample
from win32com.client import constants
from distutils.spawn import find_executable
from uuids import product_codes
import tempfile

# Settings can be overridden in config.py below
# 0 for official python.org releases
# 1 for intermediate releases by anybody, with
# a new product code for every package.
snapshot = 1
# 1 means that file extension is px, not py,
# and binaries start with x
testpackage = 0
# Location of build tree
srcdir = os.path.abspath("../..")
# Text to be displayed as the version in dialogs etc.
# goes into file name and ProductCode. Defaults to
# current_version.day for Snapshot, current_version otherwise
full_current_version = None
# Is Tcl available at all?
have_tcl = True
# path to PCbuild directory
PCBUILD="PCbuild"
# msvcrt version
MSVCR = "90"
# Name of certificate in default store to sign MSI with
certname = None
# Make a zip file containing the PDB files for this build?
pdbzip = True

try:
    from config import *
except ImportError:
    pass

# Extract current version from Include/patchlevel.h
lines = open(srcdir + "/Include/patchlevel.h").readlines()
major = minor = micro = level = serial = None
levels = {
    'PY_RELEASE_LEVEL_ALPHA':0xA,
    'PY_RELEASE_LEVEL_BETA': 0xB,
    'PY_RELEASE_LEVEL_GAMMA':0xC,
    'PY_RELEASE_LEVEL_FINAL':0xF
    }
for l in lines:
    if not l.startswith("#define"):
        continue
    l = l.split()
    if len(l) != 3:
        continue
    _, name, value = l
    if name == 'PY_MAJOR_VERSION': major = value
    if name == 'PY_MINOR_VERSION': minor = value
    if name == 'PY_MICRO_VERSION': micro = value
    if name == 'PY_RELEASE_LEVEL': level = levels[value]
    if name == 'PY_RELEASE_SERIAL': serial = value

short_version = major+"."+minor
# See PC/make_versioninfo.c
FIELD3 = 1000*int(micro) + 10*level + int(serial)
current_version = "%s.%d" % (short_version, FIELD3)

# This should never change. The UpgradeCode of this package can be
# used in the Upgrade table of future packages to make the future
# package replace this one. See "UpgradeCode Property".
# upgrade_code gets set to upgrade_code_64 when we have determined
# that the target is Win64.
upgrade_code_snapshot='{92A24481-3ECB-40FC-8836-04B7966EC0D5}'
upgrade_code='{65E6DE48-A358-434D-AA4F-4AF72DB4718F}'
upgrade_code_64='{6A965A0C-6EE6-4E3A-9983-3263F56311EC}'

if snapshot:
    current_version = "%s.%s.%s" % (major, minor, int(time.time()/3600/24))
    product_code = msilib.gen_uuid()
else:
    product_code = product_codes[current_version]

if full_current_version is None:
    full_current_version = current_version

extensions = [
    'bz2.pyd',
    'pyexpat.pyd',
    'select.pyd',
    'unicodedata.pyd',
    'winsound.pyd',
    '_elementtree.pyd',
    '_bsddb.pyd',
    '_socket.pyd',
    '_ssl.pyd',
    '_testcapi.pyd',
    '_tkinter.pyd',
    '_msi.pyd',
    '_ctypes.pyd',
    '_ctypes_test.pyd',
    '_sqlite3.pyd',
    '_hashlib.pyd',
    '_multiprocessing.pyd'
]

# Well-known component UUIDs
# These are needed for SharedDLLs reference counter; if
# a different UUID was used for each incarnation of, say,
# python24.dll, an upgrade would set the reference counter
# from 1 to 2 (due to what I consider a bug in MSI)
# Using the same UUID is fine since these files are versioned,
# so Installer will always keep the newest version.
# NOTE: All uuids are self generated.
pythondll_uuid = {
    "24":"{9B81E618-2301-4035-AC77-75D9ABEB7301}",
    "25":"{2e41b118-38bd-4c1b-a840-6977efd1b911}",
    "26":"{34ebecac-f046-4e1c-b0e3-9bac3cdaacfa}",
    "27":"{4fe21c76-1760-437b-a2f2-99909130a175}",
    } [major+minor]

# Compute the name that Sphinx gives to the docfile
docfile = ""
if int(micro):
    docfile = micro
if level < 0xf:
    if level == 0xC:
        docfile += "rc%s" % (serial,)
    else:
        docfile += '%x%s' % (level, serial)
docfile = 'python%s%s%s.chm' % (major, minor, docfile)

# Build the mingw import library, libpythonXY.a
# This requires 'nm' and 'dlltool' executables on your PATH
def build_mingw_lib(lib_file, def_file, dll_file, mingw_lib):
    warning = "WARNING: %s - libpythonXX.a not built"
    nm = find_executable('nm')
    dlltool = find_executable('dlltool')

    if not nm or not dlltool:
        print warning % "nm and/or dlltool were not found"
        return False

    nm_command = '%s -Cs %s' % (nm, lib_file)
    dlltool_command = "%s --dllname %s --def %s --output-lib %s" % \
        (dlltool, dll_file, def_file, mingw_lib)
    export_match = re.compile(r"^_imp__(.*) in python\d+\.dll").match

    f = open(def_file,'w')
    print >>f, "LIBRARY %s" % dll_file
    print >>f, "EXPORTS"

    nm_pipe = os.popen(nm_command)
    for line in nm_pipe.readlines():
        m = export_match(line)
        if m:
            print >>f, m.group(1)
    f.close()
    exit = nm_pipe.close()

    if exit:
        print warning % "nm did not run successfully"
        return False

    if os.system(dlltool_command) != 0:
        print warning % "dlltool did not run successfully"
        return False

    return True

# Target files (.def and .a) go in PCBuild directory
lib_file = os.path.join(srcdir, PCBUILD, "python%s%s.lib" % (major, minor))
def_file = os.path.join(srcdir, PCBUILD, "python%s%s.def" % (major, minor))
dll_file = "python%s%s.dll" % (major, minor)
mingw_lib = os.path.join(srcdir, PCBUILD, "libpython%s%s.a" % (major, minor))

have_mingw = build_mingw_lib(lib_file, def_file, dll_file, mingw_lib)

# Determine the target architecture
if os.system("nmake /nologo /c /f msisupport.mak") != 0:
    raise RuntimeError("'nmake /f msisupport.mak' failed")
dll_path = os.path.join(srcdir, PCBUILD, dll_file)
msilib.set_arch_from_file(dll_path)
if msilib.pe_type(dll_path) != msilib.pe_type("msisupport.dll"):
    raise SystemError, "msisupport.dll for incorrect architecture"
if msilib.Win64:
    upgrade_code = upgrade_code_64
    # Bump the last digit of the code by one, so that 32-bit and 64-bit
    # releases get separate product codes
    digit = hex((int(product_code[-2],16)+1)%16)[-1]
    product_code = product_code[:-2] + digit + '}'

if testpackage:
    ext = 'px'
    testprefix = 'x'
else:
    ext = 'py'
    testprefix = ''

if msilib.Win64:
    SystemFolderName = "[System64Folder]"
    registry_component = 4|256
else:
    SystemFolderName = "[SystemFolder]"
    registry_component = 4

msilib.reset()

# condition in which to install pythonxy.dll in system32:
# a) it is Windows 9x or
# b) it is NT, the user is privileged, and has chosen per-machine installation
sys32cond = "(Windows9x or (Privileged and ALLUSERS))"

def build_database():
    """Generate an empty database, with just the schema and the
    Summary information stream."""
    if snapshot:
        uc = upgrade_code_snapshot
    else:
        uc = upgrade_code
    if msilib.Win64:
        productsuffix = " (64-bit)"
    else:
        productsuffix = ""
    # schema represents the installer 2.0 database schema.
    # sequence is the set of standard sequences
    # (ui/execute, admin/advt/install)
    msiname = "python-%s%s.msi" % (full_current_version, msilib.arch_ext)
    db = msilib.init_database(msiname,
                  schema, ProductName="Python "+full_current_version+productsuffix,
                  ProductCode=product_code,
                  ProductVersion=current_version,
                  Manufacturer=u"Python Software Foundation",
                  request_uac = True)
    # The default sequencing of the RemoveExistingProducts action causes
    # removal of files that got just installed. Place it after
    # InstallInitialize, so we first uninstall everything, but still roll
    # back in case the installation is interrupted
    msilib.change_sequence(sequence.InstallExecuteSequence,
                           "RemoveExistingProducts", 1510)
    msilib.add_tables(db, sequence)
    # We cannot set ALLUSERS in the property table, as this cannot be
    # reset if the user choses a per-user installation. Instead, we
    # maintain WhichUsers, which can be "ALL" or "JUSTME". The UI manages
    # this property, and when the execution starts, ALLUSERS is set
    # accordingly.
    add_data(db, "Property", [("UpgradeCode", uc),
                              ("WhichUsers", "ALL"),
                              ("ProductLine", "Python%s%s" % (major, minor)),
                             ])
    db.Commit()
    return db, msiname

def remove_old_versions(db):
    "Fill the upgrade table."
    start = "%s.%s.0" % (major, minor)
    # This requests that feature selection states of an older
    # installation should be forwarded into this one. Upgrading
    # requires that both the old and the new installation are
    # either both per-machine or per-user.
    migrate_features = 1
    # See "Upgrade Table". We remove releases with the same major and
    # minor version. For an snapshot, we remove all earlier snapshots. For
    # a release, we remove all snapshots, and all earlier releases.
    if snapshot:
        add_data(db, "Upgrade",
            [(upgrade_code_snapshot, start,
              current_version,
              None,                     # Ignore language
              migrate_features,
              None,                     # Migrate ALL features
              "REMOVEOLDSNAPSHOT")])
        props = "REMOVEOLDSNAPSHOT"
    else:
        add_data(db, "Upgrade",
            [(upgrade_code, start, current_version,
              None, migrate_features, None, "REMOVEOLDVERSION"),
             (upgrade_code_snapshot, start, "%s.%d.0" % (major, int(minor)+1),
              None, migrate_features, None, "REMOVEOLDSNAPSHOT")])
        props = "REMOVEOLDSNAPSHOT;REMOVEOLDVERSION"

    props += ";TARGETDIR;DLLDIR"
    # Installer collects the product codes of the earlier releases in
    # these properties. In order to allow modification of the properties,
    # they must be declared as secure. See "SecureCustomProperties Property"
    add_data(db, "Property", [("SecureCustomProperties", props)])

class PyDialog(Dialog):
    """Dialog class with a fixed layout: controls at the top, then a ruler,
    then a list of buttons: back, next, cancel. Optionally a bitmap at the
    left."""
    def __init__(self, *args, **kw):
        """Dialog(database, name, x, y, w, h, attributes, title, first,
        default, cancel, bitmap=true)"""
        Dialog.__init__(self, *args)
        ruler = self.h - 36
        bmwidth = 152*ruler/328
        if kw.get("bitmap", True):
            self.bitmap("Bitmap", 0, 0, bmwidth, ruler, "PythonWin")
        self.line("BottomLine", 0, ruler, self.w, 0)

    def title(self, title):
        "Set the title text of the dialog at the top."
        # name, x, y, w, h, flags=Visible|Enabled|Transparent|NoPrefix,
        # text, in VerdanaBold10
        self.text("Title", 135, 10, 220, 60, 0x30003,
                  r"{\VerdanaBold10}%s" % title)

    def back(self, title, next, name = "Back", active = 1):
        """Add a back button with a given title, the tab-next button,
        its name in the Control table, possibly initially disabled.

        Return the button, so that events can be associated"""
        if active:
            flags = 3 # Visible|Enabled
        else:
            flags = 1 # Visible
        return self.pushbutton(name, 180, self.h-27 , 56, 17, flags, title, next)

    def cancel(self, title, next, name = "Cancel", active = 1):
        """Add a cancel button with a given title, the tab-next button,
        its name in the Control table, possibly initially disabled.

        Return the button, so that events can be associated"""
        if active:
            flags = 3 # Visible|Enabled
        else:
            flags = 1 # Visible
        return self.pushbutton(name, 304, self.h-27, 56, 17, flags, title, next)

    def next(self, title, next, name = "Next", active = 1):
        """Add a Next button with a given title, the tab-next button,
        its name in the Control table, possibly initially disabled.

        Return the button, so that events can be associated"""
        if active:
            flags = 3 # Visible|Enabled
        else:
            flags = 1 # Visible
        return self.pushbutton(name, 236, self.h-27, 56, 17, flags, title, next)

    def xbutton(self, name, title, next, xpos):
        """Add a button with a given title, the tab-next button,
        its name in the Control table, giving its x position; the
        y-position is aligned with the other buttons.

        Return the button, so that events can be associated"""
        return self.pushbutton(name, int(self.w*xpos - 28), self.h-27, 56, 17, 3, title, next)

def add_ui(db):
    x = y = 50
    w = 370
    h = 300
    title = "[ProductName] Setup"

    # see "Dialog Style Bits"
    modal = 3      # visible | modal
    modeless = 1   # visible
    track_disk_space = 32

    add_data(db, 'ActionText', uisample.ActionText)
    add_data(db, 'UIText', uisample.UIText)

    # Bitmaps
    if not os.path.exists(srcdir+r"\PC\python_icon.exe"):
        raise "Run icons.mak in PC directory"
    add_data(db, "Binary",
             [("PythonWin", msilib.Binary(r"%s\PCbuild\installer.bmp" % srcdir)), # 152x328 pixels
              ("py.ico",msilib.Binary(srcdir+r"\PC\py.ico")),
             ])
    add_data(db, "Icon",
             [("python_icon.exe", msilib.Binary(srcdir+r"\PC\python_icon.exe"))])

    # Scripts
    # CheckDir sets TargetExists if TARGETDIR exists.
    # UpdateEditIDLE sets the REGISTRY.tcl component into
    # the installed/uninstalled state according to both the
    # Extensions and TclTk features.
    add_data(db, "Binary", [("Script", msilib.Binary("msisupport.dll"))])
    # See "Custom Action Type 1"
    if msilib.Win64:
        CheckDir = "CheckDir"
        UpdateEditIDLE = "UpdateEditIDLE"
    else:
        CheckDir =  "_CheckDir@4"
        UpdateEditIDLE = "_UpdateEditIDLE@4"
    add_data(db, "CustomAction",
        [("CheckDir", 1, "Script", CheckDir)])
    if have_tcl:
        add_data(db, "CustomAction",
        [("UpdateEditIDLE", 1, "Script", UpdateEditIDLE)])

    # UI customization properties
    add_data(db, "Property",
             # See "DefaultUIFont Property"
             [("DefaultUIFont", "DlgFont8"),
              # See "ErrorDialog Style Bit"
              ("ErrorDialog", "ErrorDlg"),
              ("Progress1", "Install"),   # modified in maintenance type dlg
              ("Progress2", "installs"),
              ("MaintenanceForm_Action", "Repair")])

    # Fonts, see "TextStyle Table"
    add_data(db, "TextStyle",
             [("DlgFont8", "Tahoma", 9, None, 0),
              ("DlgFontBold8", "Tahoma", 8, None, 1), #bold
              ("VerdanaBold10", "Verdana", 10, None, 1),
              ("VerdanaRed9", "Verdana", 9, 255, 0),
             ])

    compileargs = r'-Wi "[TARGETDIR]Lib\compileall.py" -f -x "bad_coding|badsyntax|site-packages|py3_" "[TARGETDIR]Lib"'
    lib2to3args = r'-c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()"'
    # See "CustomAction Table"
    add_data(db, "CustomAction", [
        # msidbCustomActionTypeFirstSequence + msidbCustomActionTypeTextData + msidbCustomActionTypeProperty
        # See "Custom Action Type 51",
        # "Custom Action Execution Scheduling Options"
        ("InitialTargetDir", 307, "TARGETDIR",
         "[WindowsVolume]Python%s%s" % (major, minor)),
        ("SetDLLDirToTarget", 307, "DLLDIR", "[TARGETDIR]"),
        ("SetDLLDirToSystem32", 307, "DLLDIR", SystemFolderName),
        # msidbCustomActionTypeExe + msidbCustomActionTypeSourceFile
        # See "Custom Action Type 18"
        ("CompilePyc", 18, "python.exe", compileargs),
        ("CompilePyo", 18, "python.exe", "-O "+compileargs),
        ("CompileGrammar", 18, "python.exe", lib2to3args),
        ])

    # UI Sequences, see "InstallUISequence Table", "Using a Sequence Table"
    # Numbers indicate sequence; see sequence.py for how these action integrate
    add_data(db, "InstallUISequence",
             [("PrepareDlg", "Not Privileged or Windows9x or Installed", 140),
              ("WhichUsersDlg", "Privileged and not Windows9x and not Installed", 141),
              ("InitialTargetDir", 'TARGETDIR=""', 750),
              # In the user interface, assume all-users installation if privileged.
              ("SetDLLDirToSystem32", 'DLLDIR="" and ' + sys32cond, 751),
              ("SetDLLDirToTarget", 'DLLDIR="" and not ' + sys32cond, 752),
              ("SelectDirectoryDlg", "Not Installed", 1230),
              # XXX no support for resume installations yet
              #("ResumeDlg", "Installed AND (RESUME OR Preselected)", 1240),
              ("MaintenanceTypeDlg", "Installed AND NOT RESUME AND NOT Preselected", 1250),
              ("ProgressDlg", None, 1280)])
    add_data(db, "AdminUISequence",
             [("InitialTargetDir", 'TARGETDIR=""', 750),
              ("SetDLLDirToTarget", 'DLLDIR=""', 751),
             ])

    # Execute Sequences
    add_data(db, "InstallExecuteSequence",
            [("InitialTargetDir", 'TARGETDIR=""', 750),
             ("SetDLLDirToSystem32", 'DLLDIR="" and ' + sys32cond, 751),
             ("SetDLLDirToTarget", 'DLLDIR="" and not ' + sys32cond, 752),
             ("UpdateEditIDLE", None, 1050),
             ("CompilePyc", "COMPILEALL", 6800),
             ("CompilePyo", "COMPILEALL", 6801),
             ("CompileGrammar", "COMPILEALL", 6802),
            ])
    add_data(db, "AdminExecuteSequence",
            [("InitialTargetDir", 'TARGETDIR=""', 750),
             ("SetDLLDirToTarget", 'DLLDIR=""', 751),
             ("CompilePyc", "COMPILEALL", 6800),
             ("CompilePyo", "COMPILEALL", 6801),
             ("CompileGrammar", "COMPILEALL", 6802),
            ])

    #####################################################################
    # Standard dialogs: FatalError, UserExit, ExitDialog
    fatal=PyDialog(db, "FatalError", x, y, w, h, modal, title,
                 "Finish", "Finish", "Finish")
    fatal.title("[ProductName] Installer ended prematurely")
    fatal.back("< Back", "Finish", active = 0)
    fatal.cancel("Cancel", "Back", active = 0)
    fatal.text("Description1", 135, 70, 220, 80, 0x30003,
               "[ProductName] setup ended prematurely because of an error.  Your system has not been modified.  To install this program at a later time, please run the installation again.")
    fatal.text("Description2", 135, 155, 220, 20, 0x30003,
               "Click the Finish button to exit the Installer.")
    c=fatal.next("Finish", "Cancel", name="Finish")
    # See "ControlEvent Table". Parameters are the event, the parameter
    # to the action, and optionally the condition for the event, and the order
    # of events.
    c.event("EndDialog", "Exit")

    user_exit=PyDialog(db, "UserExit", x, y, w, h, modal, title,
                 "Finish", "Finish", "Finish")
    user_exit.title("[ProductName] Installer was interrupted")
    user_exit.back("< Back", "Finish", active = 0)
    user_exit.cancel("Cancel", "Back", active = 0)
    user_exit.text("Description1", 135, 70, 220, 80, 0x30003,
               "[ProductName] setup was interrupted.  Your system has not been modified.  "
               "To install this program at a later time, please run the installation again.")
    user_exit.text("Description2", 135, 155, 220, 20, 0x30003,
               "Click the Finish button to exit the Installer.")
    c = user_exit.next("Finish", "Cancel", name="Finish")
    c.event("EndDialog", "Exit")

    exit_dialog = PyDialog(db, "ExitDialog", x, y, w, h, modal, title,
                         "Finish", "Finish", "Finish")
    exit_dialog.title("Complete the [ProductName] Installer")
    exit_dialog.back("< Back", "Finish", active = 0)
    exit_dialog.cancel("Cancel", "Back", active = 0)
    exit_dialog.text("Acknowledgements", 135, 95, 220, 120, 0x30003,
      "Special Windows thanks to:\n"
      "    Mark Hammond, without whose years of freely \n"
      "    shared Windows expertise, Python for Windows \n"
      "    would still be Python for DOS.")

    c = exit_dialog.text("warning", 135, 200, 220, 40, 0x30003,
            "{\\VerdanaRed9}Warning: Python 3.3.0 is the last "
            "Python release for Windows 2000.")
    c.condition("Hide", "VersionNT > 500")

    exit_dialog.text("Description", 135, 235, 220, 20, 0x30003,
               "Click the Finish button to exit the Installer.")
    c = exit_dialog.next("Finish", "Cancel", name="Finish")
    c.event("EndDialog", "Return")

    #####################################################################
    # Required dialog: FilesInUse, ErrorDlg
    inuse = PyDialog(db, "FilesInUse",
                     x, y, w, h,
                     19,                # KeepModeless|Modal|Visible
                     title,
                     "Retry", "Retry", "Retry", bitmap=False)
    inuse.text("Title", 15, 6, 200, 15, 0x30003,
               r"{\DlgFontBold8}Files in Use")
    inuse.text("Description", 20, 23, 280, 20, 0x30003,
               "Some files that need to be updated are currently in use.")
    inuse.text("Text", 20, 55, 330, 50, 3,
               "The following applications are using files that need to be updated by this setup. Close these applications and then click Retry to continue the installation or Cancel to exit it.")
    inuse.control("List", "ListBox", 20, 107, 330, 130, 7, "FileInUseProcess",
                  None, None, None)
    c=inuse.back("Exit", "Ignore", name="Exit")
    c.event("EndDialog", "Exit")
    c=inuse.next("Ignore", "Retry", name="Ignore")
    c.event("EndDialog", "Ignore")
    c=inuse.cancel("Retry", "Exit", name="Retry")
    c.event("EndDialog","Retry")

    # See "Error Dialog". See "ICE20" for the required names of the controls.
    error = Dialog(db, "ErrorDlg",
                   50, 10, 330, 101,
                   65543,       # Error|Minimize|Modal|Visible
                   title,
                   "ErrorText", None, None)
    error.text("ErrorText", 50,9,280,48,3, "")
    error.control("ErrorIcon", "Icon", 15, 9, 24, 24, 5242881, None, "py.ico", None, None)
    error.pushbutton("N",120,72,81,21,3,"No",None).event("EndDialog","ErrorNo")
    error.pushbutton("Y",240,72,81,21,3,"Yes",None).event("EndDialog","ErrorYes")
    error.pushbutton("A",0,72,81,21,3,"Abort",None).event("EndDialog","ErrorAbort")
    error.pushbutton("C",42,72,81,21,3,"Cancel",None).event("EndDialog","ErrorCancel")
    error.pushbutton("I",81,72,81,21,3,"Ignore",None).event("EndDialog","ErrorIgnore")
    error.pushbutton("O",159,72,81,21,3,"Ok",None).event("EndDialog","ErrorOk")
    error.pushbutton("R",198,72,81,21,3,"Retry",None).event("EndDialog","ErrorRetry")

    #####################################################################
    # Global "Query Cancel" dialog
    cancel = Dialog(db, "CancelDlg", 50, 10, 260, 85, 3, title,
                    "No", "No", "No")
    cancel.text("Text", 48, 15, 194, 30, 3,
                "Are you sure you want to cancel [ProductName] installation?")
    cancel.control("Icon", "Icon", 15, 15, 24, 24, 5242881, None,
                   "py.ico", None, None)
    c=cancel.pushbutton("Yes", 72, 57, 56, 17, 3, "Yes", "No")
    c.event("EndDialog", "Exit")

    c=cancel.pushbutton("No", 132, 57, 56, 17, 3, "No", "Yes")
    c.event("EndDialog", "Return")

    #####################################################################
    # Global "Wait for costing" dialog
    costing = Dialog(db, "WaitForCostingDlg", 50, 10, 260, 85, modal, title,
                     "Return", "Return", "Return")
    costing.text("Text", 48, 15, 194, 30, 3,
                 "Please wait while the installer finishes determining your disk space requirements.")
    costing.control("Icon", "Icon", 15, 15, 24, 24, 5242881, None,
                    "py.ico", None, None)
    c = costing.pushbutton("Return", 102, 57, 56, 17, 3, "Return", None)
    c.event("EndDialog", "Exit")

    #####################################################################
    # Preparation dialog: no user input except cancellation
    prep = PyDialog(db, "PrepareDlg", x, y, w, h, modeless, title,
                    "Cancel", "Cancel", "Cancel")
    prep.text("Description", 135, 70, 220, 40, 0x30003,
              "Please wait while the Installer prepares to guide you through the installation.")
    prep.title("Welcome to the [ProductName] Installer")
    c=prep.text("ActionText", 135, 110, 220, 20, 0x30003, "Pondering...")
    c.mapping("ActionText", "Text")
    c=prep.text("ActionData", 135, 135, 220, 30, 0x30003, None)
    c.mapping("ActionData", "Text")
    prep.back("Back", None, active=0)
    prep.next("Next", None, active=0)
    c=prep.cancel("Cancel", None)
    c.event("SpawnDialog", "CancelDlg")

    #####################################################################
    # Target directory selection
    seldlg = PyDialog(db, "SelectDirectoryDlg", x, y, w, h, modal, title,
                    "Next", "Next", "Cancel")
    seldlg.title("Select Destination Directory")
    c = seldlg.text("Existing", 135, 25, 235, 30, 0x30003,
                    "{\VerdanaRed9}This update will replace your existing [ProductLine] installation.")
    c.condition("Hide", 'REMOVEOLDVERSION="" and REMOVEOLDSNAPSHOT=""')
    seldlg.text("Description", 135, 50, 220, 40, 0x30003,
               "Please select a directory for the [ProductName] files.")

    seldlg.back("< Back", None, active=0)
    c = seldlg.next("Next >", "Cancel")
    c.event("DoAction", "CheckDir", "TargetExistsOk<>1", order=1)
    # If the target exists, but we found that we are going to remove old versions, don't bother
    # confirming that the target directory exists. Strictly speaking, we should determine that
    # the target directory is indeed the target of the product that we are going to remove, but
    # I don't know how to do that.
    c.event("SpawnDialog", "ExistingDirectoryDlg", 'TargetExists=1 and REMOVEOLDVERSION="" and REMOVEOLDSNAPSHOT=""', 2)
    c.event("SetTargetPath", "TARGETDIR", 'TargetExists=0 or REMOVEOLDVERSION<>"" or REMOVEOLDSNAPSHOT<>""', 3)
    c.event("SpawnWaitDialog", "WaitForCostingDlg", "CostingComplete=1", 4)
    c.event("NewDialog", "SelectFeaturesDlg", 'TargetExists=0 or REMOVEOLDVERSION<>"" or REMOVEOLDSNAPSHOT<>""', 5)

    c = seldlg.cancel("Cancel", "DirectoryCombo")
    c.event("SpawnDialog", "CancelDlg")

    seldlg.control("DirectoryCombo", "DirectoryCombo", 135, 70, 172, 80, 393219,
                   "TARGETDIR", None, "DirectoryList", None)
    seldlg.control("DirectoryList", "DirectoryList", 135, 90, 208, 136, 3, "TARGETDIR",
                   None, "PathEdit", None)
    seldlg.control("PathEdit", "PathEdit", 135, 230, 206, 16, 3, "TARGETDIR", None, "Next", None)
    c = seldlg.pushbutton("Up", 306, 70, 18, 18, 3, "Up", None)
    c.event("DirectoryListUp", "0")
    c = seldlg.pushbutton("NewDir", 324, 70, 30, 18, 3, "New", None)
    c.event("DirectoryListNew", "0")

    #####################################################################
    # SelectFeaturesDlg
    features = PyDialog(db, "SelectFeaturesDlg", x, y, w, h, modal|track_disk_space,
                        title, "Tree", "Next", "Cancel")
    features.title("Customize [ProductName]")
    features.text("Description", 135, 35, 220, 15, 0x30003,
                  "Select the way you want features to be installed.")
    features.text("Text", 135,45,220,30, 3,
                  "Click on the icons in the tree below to change the way features will be installed.")

    c=features.back("< Back", "Next")
    c.event("NewDialog", "SelectDirectoryDlg")

    c=features.next("Next >", "Cancel")
    c.mapping("SelectionNoItems", "Enabled")
    c.event("SpawnDialog", "DiskCostDlg", "OutOfDiskSpace=1", order=1)
    c.event("EndDialog", "Return", "OutOfDiskSpace<>1", order=2)

    c=features.cancel("Cancel", "Tree")
    c.event("SpawnDialog", "CancelDlg")

    # The browse property is not used, since we have only a single target path (selected already)
    features.control("Tree", "SelectionTree", 135, 75, 220, 95, 7, "_BrowseProperty",
                     "Tree of selections", "Back", None)

    #c=features.pushbutton("Reset", 42, 243, 56, 17, 3, "Reset", "DiskCost")
    #c.mapping("SelectionNoItems", "Enabled")
    #c.event("Reset", "0")

    features.control("Box", "GroupBox", 135, 170, 225, 90, 1, None, None, None, None)

    c=features.xbutton("DiskCost", "Disk &Usage", None, 0.10)
    c.mapping("SelectionNoItems","Enabled")
    c.event("SpawnDialog", "DiskCostDlg")

    c=features.xbutton("Advanced", "Advanced", None, 0.30)
    c.event("SpawnDialog", "AdvancedDlg")

    c=features.text("ItemDescription", 140, 180, 210, 30, 3,
                  "Multiline description of the currently selected item.")
    c.mapping("SelectionDescription","Text")

    c=features.text("ItemSize", 140, 210, 210, 45, 3,
                    "The size of the currently selected item.")
    c.mapping("SelectionSize", "Text")

    #####################################################################
    # Disk cost
    cost = PyDialog(db, "DiskCostDlg", x, y, w, h, modal, title,
                    "OK", "OK", "OK", bitmap=False)
    cost.text("Title", 15, 6, 200, 15, 0x30003,
              "{\DlgFontBold8}Disk Space Requirements")
    cost.text("Description", 20, 20, 280, 20, 0x30003,
              "The disk space required for the installation of the selected features.")
    cost.text("Text", 20, 53, 330, 60, 3,
              "The highlighted volumes (if any) do not have enough disk space "
              "available for the currently selected features.  You can either "
              "remove some files from the highlighted volumes, or choose to "
              "install less features onto local drive(s), or select different "
              "destination drive(s).")
    cost.control("VolumeList", "VolumeCostList", 20, 100, 330, 150, 393223,
                 None, "{120}{70}{70}{70}{70}", None, None)
    cost.xbutton("OK", "Ok", None, 0.5).event("EndDialog", "Return")

    #####################################################################
    # WhichUsers Dialog. Only available on NT, and for privileged users.
    # This must be run before FindRelatedProducts, because that will
    # take into account whether the previous installation was per-user
    # or per-machine. We currently don't support going back to this
    # dialog after "Next" was selected; to support this, we would need to
    # find how to reset the ALLUSERS property, and how to re-run
    # FindRelatedProducts.
    # On Windows9x, the ALLUSERS property is ignored on the command line
    # and in the Property table, but installer fails according to the documentation
    # if a dialog attempts to set ALLUSERS.
    whichusers = PyDialog(db, "WhichUsersDlg", x, y, w, h, modal, title,
                        "AdminInstall", "Next", "Cancel")
    whichusers.title("Select whether to install [ProductName] for all users of this computer.")
    # A radio group with two options: allusers, justme
    g = whichusers.radiogroup("AdminInstall", 135, 60, 235, 80, 3,
                              "WhichUsers", "", "Next")
    g.condition("Disable", "VersionNT=600") # Not available on Vista and Windows 2008
    g.add("ALL", 0, 5, 150, 20, "Install for all users")
    g.add("JUSTME", 0, 25, 235, 20, "Install just for me (not available on Windows Vista)")

    whichusers.back("Back", None, active=0)

    c = whichusers.next("Next >", "Cancel")
    c.event("[ALLUSERS]", "1", 'WhichUsers="ALL"', 1)
    c.event("EndDialog", "Return", order = 2)

    c = whichusers.cancel("Cancel", "AdminInstall")
    c.event("SpawnDialog", "CancelDlg")

    #####################################################################
    # Advanced Dialog.
    advanced = PyDialog(db, "AdvancedDlg", x, y, w, h, modal, title,
                        "CompilePyc", "Ok", "Ok")
    advanced.title("Advanced Options for [ProductName]")
    # A radio group with two options: allusers, justme
    advanced.checkbox("CompilePyc", 135, 60, 230, 50, 3,
                      "COMPILEALL", "Compile .py files to byte code after installation", "Ok")

    c = advanced.cancel("Ok", "CompilePyc", name="Ok") # Button just has location of cancel button.
    c.event("EndDialog", "Return")

    #####################################################################
    # Existing Directory dialog
    dlg = Dialog(db, "ExistingDirectoryDlg", 50, 30, 200, 80, modal, title,
                   "No", "No", "No")
    dlg.text("Title", 10, 20, 180, 40, 3,
             "[TARGETDIR] exists. Are you sure you want to overwrite existing files?")
    c=dlg.pushbutton("Yes", 30, 60, 55, 17, 3, "Yes", "No")
    c.event("[TargetExists]", "0", order=1)
    c.event("[TargetExistsOk]", "1", order=2)
    c.event("EndDialog", "Return", order=3)
    c=dlg.pushbutton("No", 115, 60, 55, 17, 3, "No", "Yes")
    c.event("EndDialog", "Return")

    #####################################################################
    # Installation Progress dialog (modeless)
    progress = PyDialog(db, "ProgressDlg", x, y, w, h, modeless, title,
                        "Cancel", "Cancel", "Cancel", bitmap=False)
    progress.text("Title", 20, 15, 200, 15, 0x30003,
                  "{\DlgFontBold8}[Progress1] [ProductName]")
    progress.text("Text", 35, 65, 300, 30, 3,
                  "Please wait while the Installer [Progress2] [ProductName]. "
                  "This may take several minutes.")
    progress.text("StatusLabel", 35, 100, 35, 20, 3, "Status:")

    c=progress.text("ActionText", 70, 100, w-70, 20, 3, "Pondering...")
    c.mapping("ActionText", "Text")

    #c=progress.text("ActionData", 35, 140, 300, 20, 3, None)
    #c.mapping("ActionData", "Text")

    c=progress.control("ProgressBar", "ProgressBar", 35, 120, 300, 10, 65537,
                       None, "Progress done", None, None)
    c.mapping("SetProgress", "Progress")

    progress.back("< Back", "Next", active=False)
    progress.next("Next >", "Cancel", active=False)
    progress.cancel("Cancel", "Back").event("SpawnDialog", "CancelDlg")

    # Maintenance type: repair/uninstall
    maint = PyDialog(db, "MaintenanceTypeDlg", x, y, w, h, modal, title,
                     "Next", "Next", "Cancel")
    maint.title("Welcome to the [ProductName] Setup Wizard")
    maint.text("BodyText", 135, 63, 230, 42, 3,
               "Select whether you want to repair or remove [ProductName].")
    g=maint.radiogroup("RepairRadioGroup", 135, 108, 230, 60, 3,
                        "MaintenanceForm_Action", "", "Next")
    g.add("Change", 0, 0, 200, 17, "&Change [ProductName]")
    g.add("Repair", 0, 18, 200, 17, "&Repair [ProductName]")
    g.add("Remove", 0, 36, 200, 17, "Re&move [ProductName]")

    maint.back("< Back", None, active=False)
    c=maint.next("Finish", "Cancel")
    # Change installation: Change progress dialog to "Change", then ask
    # for feature selection
    c.event("[Progress1]", "Change", 'MaintenanceForm_Action="Change"', 1)
    c.event("[Progress2]", "changes", 'MaintenanceForm_Action="Change"', 2)

    # Reinstall: Change progress dialog to "Repair", then invoke reinstall
    # Also set list of reinstalled features to "ALL"
    c.event("[REINSTALL]", "ALL", 'MaintenanceForm_Action="Repair"', 5)
    c.event("[Progress1]", "Repairing", 'MaintenanceForm_Action="Repair"', 6)
    c.event("[Progress2]", "repairs", 'MaintenanceForm_Action="Repair"', 7)
    c.event("Reinstall", "ALL", 'MaintenanceForm_Action="Repair"', 8)

    # Uninstall: Change progress to "Remove", then invoke uninstall
    # Also set list of removed features to "ALL"
    c.event("[REMOVE]", "ALL", 'MaintenanceForm_Action="Remove"', 11)
    c.event("[Progress1]", "Removing", 'MaintenanceForm_Action="Remove"', 12)
    c.event("[Progress2]", "removes", 'MaintenanceForm_Action="Remove"', 13)
    c.event("Remove", "ALL", 'MaintenanceForm_Action="Remove"', 14)

    # Close dialog when maintenance action scheduled
    c.event("EndDialog", "Return", 'MaintenanceForm_Action<>"Change"', 20)
    c.event("NewDialog", "SelectFeaturesDlg", 'MaintenanceForm_Action="Change"', 21)

    maint.cancel("Cancel", "RepairRadioGroup").event("SpawnDialog", "CancelDlg")

# See "Feature Table". The feature level is 1 for all features,
# and the feature attributes are 0 for the DefaultFeature, and
# FollowParent for all other features. The numbers are the Display
# column.
def add_features(db):
    # feature attributes:
    # msidbFeatureAttributesFollowParent == 2
    # msidbFeatureAttributesDisallowAdvertise == 8
    # Features that need to be installed with together with the main feature
    # (i.e. additional Python libraries) need to follow the parent feature.
    # Features that have no advertisement trigger (e.g. the test suite)
    # must not support advertisement
    global default_feature, tcltk, htmlfiles, tools, testsuite, ext_feature, private_crt
    default_feature = Feature(db, "DefaultFeature", "Python",
                              "Python Interpreter and Libraries",
                              1, directory = "TARGETDIR")
    shared_crt = Feature(db, "SharedCRT", "MSVCRT", "C Run-Time (system-wide)", 0,
                         level=0)
    private_crt = Feature(db, "PrivateCRT", "MSVCRT", "C Run-Time (private)", 0,
                          level=0)
    add_data(db, "Condition", [("SharedCRT", 1, sys32cond),
                               ("PrivateCRT", 1, "not "+sys32cond)])
    # We don't support advertisement of extensions
    ext_feature = Feature(db, "Extensions", "Register Extensions",
                          "Make this Python installation the default Python installation", 3,
                         parent = default_feature, attributes=2|8)
    if have_tcl:
        tcltk = Feature(db, "TclTk", "Tcl/Tk", "Tkinter, IDLE, pydoc", 5,
                    parent = default_feature, attributes=2)
    htmlfiles = Feature(db, "Documentation", "Documentation",
                        "Python HTMLHelp File", 7, parent = default_feature)
    tools = Feature(db, "Tools", "Utility Scripts",
                    "Python utility scripts (Tools/", 9,
                    parent = default_feature, attributes=2)
    testsuite = Feature(db, "Testsuite", "Test suite",
                        "Python test suite (Lib/test/)", 11,
                        parent = default_feature, attributes=2|8)

def extract_msvcr90():
    # Find the redistributable files
    if msilib.Win64:
        arch = "amd64"
    else:
        arch = "x86"
    dir = os.path.join(os.environ['VS90COMNTOOLS'], r"..\..\VC\redist\%s\Microsoft.VC90.CRT" % arch)

    result = []
    installer = msilib.MakeInstaller()
    # omit msvcm90 and msvcp90, as they aren't really needed
    files = ["Microsoft.VC90.CRT.manifest", "msvcr90.dll"]
    for f in files:
        path = os.path.join(dir, f)
        kw = {'src':path}
        if f.endswith('.dll'):
            kw['version'] = installer.FileVersion(path, 0)
            kw['language'] = installer.FileVersion(path, 1)
        result.append((f, kw))
    return result

def generate_license():
    import shutil, glob
    out = open("LICENSE.txt", "w")
    shutil.copyfileobj(open(os.path.join(srcdir, "LICENSE")), out)
    shutil.copyfileobj(open("crtlicense.txt"), out)
    for name, pat, file in (("bzip2","bzip2-*", "LICENSE"),
                      ("Berkeley DB", "db-*", "LICENSE"),
                      ("openssl", "openssl-*", "LICENSE"),
                      ("Tcl", "tcl8*", "license.terms"),
                      ("Tk", "tk8*", "license.terms"),
                      ("Tix", "tix-*", "license.terms")):
        out.write("\nThis copy of Python includes a copy of %s, which is licensed under the following terms:\n\n" % name)
        dirs = glob.glob(srcdir+"/../"+pat)
        if not dirs:
            raise ValueError, "Could not find "+srcdir+"/../"+pat
        if len(dirs) > 2:
            raise ValueError, "Multiple copies of "+pat
        dir = dirs[0]
        shutil.copyfileobj(open(os.path.join(dir, file)), out)
    out.close()

class PyDirectory(Directory):
    """By default, all components in the Python installer
    can run from source."""
    def __init__(self, *args, **kw):
        if not kw.has_key("componentflags"):
            kw['componentflags'] = 2 #msidbComponentAttributesOptional
        Directory.__init__(self, *args, **kw)

# See "File Table", "Component Table", "Directory Table",
# "FeatureComponents Table"
def add_files(db):
    cab = CAB("python")
    tmpfiles = []
    # Add all executables, icons, text files into the TARGETDIR component
    root = PyDirectory(db, cab, None, srcdir, "TARGETDIR", "SourceDir")
    default_feature.set_current()
    if not msilib.Win64:
        root.add_file("%s/w9xpopen.exe" % PCBUILD)
    root.add_file("README.txt", src="README")
    root.add_file("NEWS.txt", src="Misc/NEWS")
    generate_license()
    root.add_file("LICENSE.txt", src=os.path.abspath("LICENSE.txt"))
    root.start_component("python.exe", keyfile="python.exe")
    root.add_file("%s/python.exe" % PCBUILD)
    root.start_component("pythonw.exe", keyfile="pythonw.exe")
    root.add_file("%s/pythonw.exe" % PCBUILD)

    # msidbComponentAttributesSharedDllRefCount = 8, see "Component Table"
    dlldir = PyDirectory(db, cab, root, srcdir, "DLLDIR", ".")

    pydll = "python%s%s.dll" % (major, minor)
    pydllsrc = os.path.join(srcdir, PCBUILD, pydll)
    dlldir.start_component("DLLDIR", flags = 8, keyfile = pydll, uuid = pythondll_uuid)
    installer = msilib.MakeInstaller()
    pyversion = installer.FileVersion(pydllsrc, 0)
    if not snapshot:
        # For releases, the Python DLL has the same version as the
        # installer package.
        assert pyversion.split(".")[:3] == current_version.split(".")
    dlldir.add_file("%s/python%s%s.dll" % (PCBUILD, major, minor),
                    version=pyversion,
                    language=installer.FileVersion(pydllsrc, 1))
    DLLs = PyDirectory(db, cab, root, srcdir + "/" + PCBUILD, "DLLs", "DLLS|DLLs")

    # msvcr90.dll: Need to place the DLL and the manifest into the root directory,
    # plus another copy of the manifest in the DLLs directory, with the manifest
    # pointing to the root directory
    root.start_component("msvcr90", feature=private_crt)
    # Results are ID,keyword pairs
    manifest, crtdll = extract_msvcr90()
    root.add_file(manifest[0], **manifest[1])
    root.add_file(crtdll[0], **crtdll[1])
    # Copy the manifest
    # Actually, don't do that anymore - no DLL in DLLs should have a manifest
    # dependency on msvcr90.dll anymore, so this should not be necessary
    #manifest_dlls = manifest[0]+".root"
    #open(manifest_dlls, "w").write(open(manifest[1]['src']).read().replace("msvcr","../msvcr"))
    #DLLs.start_component("msvcr90_dlls", feature=private_crt)
    #DLLs.add_file(manifest[0], src=os.path.abspath(manifest_dlls))

    # Now start the main component for the DLLs directory;
    # no regular files have been added to the directory yet.
    DLLs.start_component()

    # Check if _ctypes.pyd exists
    have_ctypes = os.path.exists(srcdir+"/%s/_ctypes.pyd" % PCBUILD)
    if not have_ctypes:
        print "WARNING: _ctypes.pyd not found, ctypes will not be included"
        extensions.remove("_ctypes.pyd")

    # Add all .py files in Lib, except lib-tk, test
    dirs={}
    pydirs = [(root,"Lib")]
    while pydirs:
        # Commit every now and then, or else installer will complain
        db.Commit()
        parent, dir = pydirs.pop()
        if dir == ".svn" or dir.startswith("plat-"):
            continue
        elif dir in ["lib-tk", "idlelib", "Icons"]:
            if not have_tcl:
                continue
            tcltk.set_current()
        elif dir in ['test', 'tests', 'data', 'output']:
            # test: Lib, Lib/email, Lib/bsddb, Lib/ctypes, Lib/sqlite3
            # tests: Lib/distutils
            # data: Lib/email/test
            # output: Lib/test
            testsuite.set_current()
        elif not have_ctypes and dir == "ctypes":
            continue
        else:
            default_feature.set_current()
        lib = PyDirectory(db, cab, parent, dir, dir, "%s|%s" % (parent.make_short(dir), dir))
        # Add additional files
        dirs[dir]=lib
        lib.glob("*.txt")
        if dir=='site-packages':
            lib.add_file("README.txt", src="README")
            continue
        files = lib.glob("*.py")
        files += lib.glob("*.pyw")
        if files:
            # Add an entry to the RemoveFile table to remove bytecode files.
            lib.remove_pyc()
        if dir.endswith('.egg-info'):
            lib.add_file('entry_points.txt')
            lib.add_file('PKG-INFO')
            lib.add_file('top_level.txt')
            lib.add_file('zip-safe')
            continue
        if dir=='test' and parent.physical=='Lib':
            lib.add_file("185test.db")
            lib.add_file("audiotest.au")
            lib.add_file("cfgparser.1")
            lib.add_file("sgml_input.html")
            lib.add_file("testtar.tar")
            lib.add_file("test_difflib_expect.html")
            lib.add_file("check_soundcard.vbs")
            lib.add_file("empty.vbs")
            lib.add_file("Sine-1000Hz-300ms.aif")
            lib.glob("*.uue")
            lib.glob("*.pem")
            lib.glob("*.pck")
            lib.add_file("zipdir.zip")
        if dir=='tests' and parent.physical=='distutils':
            lib.add_file("Setup.sample")
        if dir=='decimaltestdata':
            lib.glob("*.decTest")
        if dir=='xmltestdata':
            lib.glob("*.xml")
            lib.add_file("test.xml.out")
        if dir=='output':
            lib.glob("test_*")
        if dir=='idlelib':
            lib.glob("*.def")
            lib.add_file("idle.bat")
        if dir=="Icons":
            lib.glob("*.gif")
            lib.add_file("idle.icns")
        if dir=="command" and parent.physical=="distutils":
            lib.glob("wininst*.exe")
        if dir=="setuptools":
            lib.add_file("cli.exe")
            lib.add_file("gui.exe")
        if dir=="lib2to3":
            lib.removefile("pickle", "*.pickle")
        if dir=="data" and parent.physical=="test" and parent.basedir.physical=="email":
            # This should contain all non-.svn files listed in subversion
            for f in os.listdir(lib.absolute):
                if f.endswith(".txt") or f==".svn":continue
                if f.endswith(".au") or f.endswith(".gif"):
                    lib.add_file(f)
                else:
                    print "WARNING: New file %s in email/test/data" % f
        for f in os.listdir(lib.absolute):
            if os.path.isdir(os.path.join(lib.absolute, f)):
                pydirs.append((lib, f))
    # Add DLLs
    default_feature.set_current()
    lib = DLLs
    lib.add_file("py.ico", src=srcdir+"/PC/py.ico")
    lib.add_file("pyc.ico", src=srcdir+"/PC/pyc.ico")
    dlls = []
    tclfiles = []
    for f in extensions:
        if f=="_tkinter.pyd":
            continue
        if not os.path.exists(srcdir + "/" + PCBUILD + "/" + f):
            print "WARNING: Missing extension", f
            continue
        dlls.append(f)
        lib.add_file(f)
    # Add sqlite
    if msilib.msi_type=="Intel64;1033":
        sqlite_arch = "/ia64"
    elif msilib.msi_type=="x64;1033":
        sqlite_arch = "/amd64"
        tclsuffix = "64"
    else:
        sqlite_arch = ""
        tclsuffix = ""
    lib.add_file("sqlite3.dll")
    if have_tcl:
        if not os.path.exists("%s/%s/_tkinter.pyd" % (srcdir, PCBUILD)):
            print "WARNING: Missing _tkinter.pyd"
        else:
            lib.start_component("TkDLLs", tcltk)
            lib.add_file("_tkinter.pyd")
            dlls.append("_tkinter.pyd")
            tcldir = os.path.normpath(srcdir+("/../tcltk%s/bin" % tclsuffix))
            for f in glob.glob1(tcldir, "*.dll"):
                lib.add_file(f, src=os.path.join(tcldir, f))
    # check whether there are any unknown extensions
    for f in glob.glob1(srcdir+"/"+PCBUILD, "*.pyd"):
        if f.endswith("_d.pyd"): continue # debug version
        if f in dlls: continue
        print "WARNING: Unknown extension", f

    # Add headers
    default_feature.set_current()
    lib = PyDirectory(db, cab, root, "include", "include", "INCLUDE|include")
    lib.glob("*.h")
    lib.add_file("pyconfig.h", src="../PC/pyconfig.h")
    # Add import libraries
    lib = PyDirectory(db, cab, root, PCBUILD, "libs", "LIBS|libs")
    for f in dlls:
        lib.add_file(f.replace('pyd','lib'))
    lib.add_file('python%s%s.lib' % (major, minor))
    # Add the mingw-format library
    if have_mingw:
        lib.add_file('libpython%s%s.a' % (major, minor))
    if have_tcl:
        # Add Tcl/Tk
        tcldirs = [(root, '../tcltk%s/lib' % tclsuffix, 'tcl')]
        tcltk.set_current()
        while tcldirs:
            parent, phys, dir = tcldirs.pop()
            lib = PyDirectory(db, cab, parent, phys, dir, "%s|%s" % (parent.make_short(dir), dir))
            if not os.path.exists(lib.absolute):
                continue
            for f in os.listdir(lib.absolute):
                if os.path.isdir(os.path.join(lib.absolute, f)):
                    tcldirs.append((lib, f, f))
                else:
                    lib.add_file(f)
    # Add tools
    tools.set_current()
    tooldir = PyDirectory(db, cab, root, "Tools", "Tools", "TOOLS|Tools")
    for f in ['i18n', 'pynche', 'Scripts', 'versioncheck', 'webchecker']:
        lib = PyDirectory(db, cab, tooldir, f, f, "%s|%s" % (tooldir.make_short(f), f))
        lib.glob("*.py")
        lib.glob("*.pyw", exclude=['pydocgui.pyw'])
        lib.remove_pyc()
        lib.glob("*.txt")
        if f == "pynche":
            x = PyDirectory(db, cab, lib, "X", "X", "X|X")
            x.glob("*.txt")
        if os.path.exists(os.path.join(lib.absolute, "README")):
            lib.add_file("README.txt", src="README")
        if f == 'Scripts':
            lib.add_file("2to3.py", src="2to3")
            if have_tcl:
                lib.start_component("pydocgui.pyw", tcltk, keyfile="pydocgui.pyw")
                lib.add_file("pydocgui.pyw")
    # Add documentation
    htmlfiles.set_current()
    lib = PyDirectory(db, cab, root, "Doc", "Doc", "DOC|Doc")
    lib.start_component("documentation", keyfile=docfile)
    lib.add_file(docfile, src="build/htmlhelp/"+docfile)

    cab.commit(db)

    for f in tmpfiles:
        os.unlink(f)

# See "Registry Table", "Component Table"
def add_registry(db):
    # File extensions, associated with the REGISTRY.def component
    # IDLE verbs depend on the tcltk feature.
    # msidbComponentAttributesRegistryKeyPath = 4
    # -1 for Root specifies "dependent on ALLUSERS property"
    tcldata = []
    if have_tcl:
        tcldata = [
            ("REGISTRY.tcl", msilib.gen_uuid(), "TARGETDIR", registry_component, None,
             "py.IDLE")]
    add_data(db, "Component",
             # msidbComponentAttributesRegistryKeyPath = 4
             [("REGISTRY", msilib.gen_uuid(), "TARGETDIR", registry_component, None,
               "InstallPath"),
              ("REGISTRY.doc", msilib.gen_uuid(), "TARGETDIR", registry_component, None,
               "Documentation"),
              ("REGISTRY.def", msilib.gen_uuid(), "TARGETDIR", registry_component,
               None, None)] + tcldata)
    # See "FeatureComponents Table".
    # The association between TclTk and pythonw.exe is necessary to make ICE59
    # happy, because the installer otherwise believes that the IDLE and PyDoc
    # shortcuts might get installed without pythonw.exe being install. This
    # is not true, since installing TclTk will install the default feature, which
    # will cause pythonw.exe to be installed.
    # REGISTRY.tcl is not associated with any feature, as it will be requested
    # through a custom action
    tcldata = []
    if have_tcl:
        tcldata = [(tcltk.id, "pythonw.exe")]
    add_data(db, "FeatureComponents",
             [(default_feature.id, "REGISTRY"),
              (htmlfiles.id, "REGISTRY.doc"),
              (ext_feature.id, "REGISTRY.def")] +
              tcldata
              )
    # Extensions are not advertised. For advertised extensions,
    # we would need separate binaries that install along with the
    # extension.
    pat = r"Software\Classes\%sPython.%sFile\shell\%s\command"
    ewi = "Edit with IDLE"
    pat2 = r"Software\Classes\%sPython.%sFile\DefaultIcon"
    pat3 = r"Software\Classes\%sPython.%sFile"
    pat4 = r"Software\Classes\%sPython.%sFile\shellex\DropHandler"
    tcl_verbs = []
    if have_tcl:
        tcl_verbs=[
             ("py.IDLE", -1, pat % (testprefix, "", ewi), "",
              r'"[TARGETDIR]pythonw.exe" "[TARGETDIR]Lib\idlelib\idle.pyw" -e "%1"',
              "REGISTRY.tcl"),
             ("pyw.IDLE", -1, pat % (testprefix, "NoCon", ewi), "",
              r'"[TARGETDIR]pythonw.exe" "[TARGETDIR]Lib\idlelib\idle.pyw" -e "%1"',
              "REGISTRY.tcl"),
        ]
    add_data(db, "Registry",
            [# Extensions
             ("py.ext", -1, r"Software\Classes\."+ext, "",
              "Python.File", "REGISTRY.def"),
             ("pyw.ext", -1, r"Software\Classes\."+ext+'w', "",
              "Python.NoConFile", "REGISTRY.def"),
             ("pyc.ext", -1, r"Software\Classes\."+ext+'c', "",
              "Python.CompiledFile", "REGISTRY.def"),
             ("pyo.ext", -1, r"Software\Classes\."+ext+'o', "",
              "Python.CompiledFile", "REGISTRY.def"),
             # MIME types
             ("py.mime", -1, r"Software\Classes\."+ext, "Content Type",
              "text/plain", "REGISTRY.def"),
             ("pyw.mime", -1, r"Software\Classes\."+ext+'w', "Content Type",
              "text/plain", "REGISTRY.def"),
             #Verbs
             ("py.open", -1, pat % (testprefix, "", "open"), "",
              r'"[TARGETDIR]python.exe" "%1" %*', "REGISTRY.def"),
             ("pyw.open", -1, pat % (testprefix, "NoCon", "open"), "",
              r'"[TARGETDIR]pythonw.exe" "%1" %*', "REGISTRY.def"),
             ("pyc.open", -1, pat % (testprefix, "Compiled", "open"), "",
              r'"[TARGETDIR]python.exe" "%1" %*', "REGISTRY.def"),
             ] + tcl_verbs + [
             #Icons
             ("py.icon", -1, pat2 % (testprefix, ""), "",
              r'[DLLs]py.ico', "REGISTRY.def"),
             ("pyw.icon", -1, pat2 % (testprefix, "NoCon"), "",
              r'[DLLs]py.ico', "REGISTRY.def"),
             ("pyc.icon", -1, pat2 % (testprefix, "Compiled"), "",
              r'[DLLs]pyc.ico', "REGISTRY.def"),
             # Descriptions
             ("py.txt", -1, pat3 % (testprefix, ""), "",
              "Python File", "REGISTRY.def"),
             ("pyw.txt", -1, pat3 % (testprefix, "NoCon"), "",
              "Python File (no console)", "REGISTRY.def"),
             ("pyc.txt", -1, pat3 % (testprefix, "Compiled"), "",
              "Compiled Python File", "REGISTRY.def"),
             # Drop Handler
             ("py.drop", -1, pat4 % (testprefix, ""), "",
              "{60254CA5-953B-11CF-8C96-00AA00B8708C}", "REGISTRY.def"),
             ("pyw.drop", -1, pat4 % (testprefix, "NoCon"), "",
              "{60254CA5-953B-11CF-8C96-00AA00B8708C}", "REGISTRY.def"),
             ("pyc.drop", -1, pat4 % (testprefix, "Compiled"), "",
              "{60254CA5-953B-11CF-8C96-00AA00B8708C}", "REGISTRY.def"),
            ])

    # Registry keys
    prefix = r"Software\%sPython\PythonCore\%s" % (testprefix, short_version)
    add_data(db, "Registry",
             [("InstallPath", -1, prefix+r"\InstallPath", "", "[TARGETDIR]", "REGISTRY"),
              ("InstallGroup", -1, prefix+r"\InstallPath\InstallGroup", "",
               "Python %s" % short_version, "REGISTRY"),
              ("PythonPath", -1, prefix+r"\PythonPath", "",
               r"[TARGETDIR]Lib;[TARGETDIR]DLLs;[TARGETDIR]Lib\lib-tk", "REGISTRY"),
              ("Documentation", -1, prefix+r"\Help\Main Python Documentation", "",
               "[TARGETDIR]Doc\\"+docfile , "REGISTRY.doc"),
              ("Modules", -1, prefix+r"\Modules", "+", None, "REGISTRY"),
              ("AppPaths", -1, r"Software\Microsoft\Windows\CurrentVersion\App Paths\Python.exe",
               "", r"[TARGETDIR]Python.exe", "REGISTRY.def"),
              ("DisplayIcon", -1,
               r"Software\Microsoft\Windows\CurrentVersion\Uninstall\%s" % product_code,
               "DisplayIcon", "[TARGETDIR]python.exe", "REGISTRY")
              ])
    # Shortcuts, see "Shortcut Table"
    add_data(db, "Directory",
             [("ProgramMenuFolder", "TARGETDIR", "."),
              ("MenuDir", "ProgramMenuFolder", "PY%s%s|%sPython %s.%s" % (major,minor,testprefix,major,minor))])
    add_data(db, "RemoveFile",
             [("MenuDir", "TARGETDIR", None, "MenuDir", 2)])
    tcltkshortcuts = []
    if have_tcl:
        tcltkshortcuts = [
              ("IDLE", "MenuDir", "IDLE|IDLE (Python GUI)", "pythonw.exe",
               tcltk.id, r'"[TARGETDIR]Lib\idlelib\idle.pyw"', None, None, "python_icon.exe", 0, None, "TARGETDIR"),
              ("PyDoc", "MenuDir", "MODDOCS|Module Docs", "pythonw.exe",
               tcltk.id, r'"[TARGETDIR]Tools\scripts\pydocgui.pyw"', None, None, "python_icon.exe", 0, None, "TARGETDIR"),
              ]
    add_data(db, "Shortcut",
             tcltkshortcuts +
             [# Advertised shortcuts: targets are features, not files
              ("Python", "MenuDir", "PYTHON|Python (command line)", "python.exe",
               default_feature.id, None, None, None, "python_icon.exe", 2, None, "TARGETDIR"),
              # Advertising the Manual breaks on (some?) Win98, and the shortcut lacks an
              # icon first.
              #("Manual", "MenuDir", "MANUAL|Python Manuals", "documentation",
              # htmlfiles.id, None, None, None, None, None, None, None),
              ## Non-advertised shortcuts: must be associated with a registry component
              ("Manual", "MenuDir", "MANUAL|Python Manuals", "REGISTRY.doc",
               "[#%s]" % docfile, None,
               None, None, None, None, None, None),
              ("Uninstall", "MenuDir", "UNINST|Uninstall Python", "REGISTRY",
               SystemFolderName+"msiexec",  "/x%s" % product_code,
               None, None, None, None, None, None),
              ])
    db.Commit()

def build_pdbzip():
    pdbexclude = ['kill_python.pdb', 'make_buildinfo.pdb',
                  'make_versioninfo.pdb']
    path = "python-%s%s-pdb.zip" % (full_current_version, msilib.arch_ext)
    pdbzip = zipfile.ZipFile(path, 'w')
    for f in glob.glob1(os.path.join(srcdir, PCBUILD), "*.pdb"):
        if f not in pdbexclude and not f.endswith('_d.pdb'):
            pdbzip.write(os.path.join(srcdir, PCBUILD, f), f)
    pdbzip.close()

db,msiname = build_database()
try:
    add_features(db)
    add_ui(db)
    add_files(db)
    add_registry(db)
    remove_old_versions(db)
    db.Commit()
finally:
    del db

# Merge CRT into MSI file. This requires the database to be closed.
mod_dir = os.path.join(os.environ["ProgramFiles"], "Common Files", "Merge Modules")
if msilib.Win64:
    modules = ["Microsoft_VC90_CRT_x86_x64.msm", "policy_9_0_Microsoft_VC90_CRT_x86_x64.msm"]
else:
    modules = ["Microsoft_VC90_CRT_x86.msm","policy_9_0_Microsoft_VC90_CRT_x86.msm"]

for i, n in enumerate(modules):
    modules[i] = os.path.join(mod_dir, n)

def merge(msi, feature, rootdir, modules):
    cab_and_filecount = []
    # Step 1: Merge databases, extract cabfiles
    m = msilib.MakeMerge2()
    m.OpenLog("merge.log")
    m.OpenDatabase(msi)
    for module in modules:
        print module
        m.OpenModule(module,0)
        m.Merge(feature, rootdir)
        print "Errors:"
        for e in m.Errors:
            print e.Type, e.ModuleTable, e.DatabaseTable
            print "   Modkeys:",
            for s in e.ModuleKeys: print s,
            print
            print "   DBKeys:",
            for s in e.DatabaseKeys: print s,
            print
        cabname = tempfile.mktemp(suffix=".cab")
        m.ExtractCAB(cabname)
        cab_and_filecount.append((cabname, len(m.ModuleFiles)))
        m.CloseModule()
    m.CloseDatabase(True)
    m.CloseLog()

    # Step 2: Add CAB files
    i = msilib.MakeInstaller()
    db = i.OpenDatabase(msi, constants.msiOpenDatabaseModeTransact)

    v = db.OpenView("SELECT LastSequence FROM Media")
    v.Execute(None)
    maxmedia = -1
    while 1:
        r = v.Fetch()
        if not r: break
        seq = r.IntegerData(1)
        if seq > maxmedia:
            maxmedia = seq
    print "Start of Media", maxmedia

    for cabname, count in cab_and_filecount:
        stream = "merged%d" % maxmedia
        msilib.add_data(db, "Media",
                [(maxmedia+1, maxmedia+count, None, "#"+stream, None, None)])
        msilib.add_stream(db, stream,  cabname)
        os.unlink(cabname)
        maxmedia += count
    # The merge module sets ALLUSERS to 1 in the property table.
    # This is undesired; delete that
    v = db.OpenView("DELETE FROM Property WHERE Property='ALLUSERS'")
    v.Execute(None)
    v.Close()
    db.Commit()

merge(msiname, "SharedCRT", "TARGETDIR", modules)

# certname (from config.py) should be (a substring of)
# the certificate subject, e.g. "Python Software Foundation"
if certname:
    os.system('signtool sign /n "%s" '
      '/t http://timestamp.verisign.com/scripts/timestamp.dll '
      '/d "Python %s" '
      '%s' % (certname, full_current_version, msiname))

if pdbzip:
    build_pdbzip()

redpajama_set_name: RedPajamaGithub


Like all children, I used to hate reciting prayers as they seemed boring and meaningless to me. In fact, I was among those who could not learn a Sanskrit shloka easily.
But as I grew older, my father made me understand the true meaning of prayer. It is not about reciting shlokas and offering food to God, but about connecting to Him and asking for His guidance as He is our creator, our father.
My father said, prayer or prarthana is asking God for spiritualistic qualities. Just like water which cleans our body, prayer cleans our atma or soul. Initially, I was unable to control my mind for even 10 minutes, but now I want to pray more and more, as every time I pray I feel pure.
When the mind is full of prayerful thoughts, everything in the world seems good and agreeable. Prayer has brought purpose in my life and given me a destination worth going to. When you start praying you will get the power to sustain yourself even in the midst of hatred with peace and love. So pray, as a true prayer never goes unanswered!


text:
Pulse of the City Honors Construction Companies for Earning 8 Consecutive Customer Satisfaction Awards
Pulse of the City News announces the most recent winners of the prestigious Pulse Award for Customer Satisfaction, and all are eight-time honorees.
Lapeer, MI, July 05, 2019 --(PR.com)-- Pulse of the City News awards those in the construction industry that provide their customers with more than just great products and services, but also an exceptional customer experience. Recently, it granted the Pulse Award to three companies that have earned high praise from satisfied customers for eight straight years.
MIB Remodeling, LLC (www.mibremodeling.com) is Northwest Houston's leading home remodeler, offering a range of services for small bathroom and kitchen remodeling projects to whole home remodels. The company focuses on creating successful partnerships with its clients throughout the life of the project, exceeding their expectations and gaining their trust through exceptional performance. The goal is to: Make It Beautiful (MIB) for each and every customer. Through consistent customer engagement and communication, MIB Remodeling provides its customers with the highest level of service. Visit its Award Page at https://www.pulseofthecitynews.com/company-details/7413v2a4x2/mib-remodeling/Houston/TX.
In business for more than 30 years, Unified Window Systems, Inc. (www.unifiedwindows.com) has five locations in New York to serve customers. The company sells and installs exterior home improvements such as windows, doors, siding, roofing, stone work, attic insulation, awnings, carports and porticos. Unified partners with great manufacturers, and its products are all custom made to fit each customer's home. With more than 100,000 jobs completed in its 30-year history, Unified is proud to boast a 99.6% customer satisfaction rating. Visit its Award Page at https://www.pulseofthecitynews.com/company-details/94z2233453/unified-window-systems-inc/Hempstead/NY.
Since 1990, Prism General Services Inc. (www.prismgeneralservices.com) in New Hyde Park, N.Y., has taken pride in providing residential and commercial restoration services due to damage from fire, smoke, water, wind, structural failure or other disaster. With a 24-hour response time that is considered by industry standards to be unparalleled, Prism General Services has successfully restored damaged properties for thousands of homeowners and business owners. The company offers the highest quality, most technically accurate service in the disaster recovery industry. Visit its Award Page at https://www.pulseofthecitynews.com/company-details/84x2037413/Prism-General-Services-Corp/New-Hyde-Park/NY.
Frank Andrews, Founder of The Stirling Center, which works with Pulse of the City in identifying building and construction companies that provide more than just great design and construction services, but also a great customer experience, says, "They are shining examples of the great contribution that leading small businesses make to the quality of our lives and communities, and we salute them!"

redpajama_set_name: RedPajamaCommonCrawl


text:
Nielsen Acquires Vizu To Measure Online Ad Effectiveness
Anthony Ha	@anthonyha / 10 years
Nielsen announced today that it's acquiring ad tech company Vizu.
This isn't the kind of deal where you have to wait months for something to happen. Executive Vice President for Ad Effectiveness Scott McKinley says it's a "plug and play acquisition," and in fact, Vizu's Ad Catalyst will be available immediately as part of Nielsen's online ad measurement tools.
When the company decided to improve its ability to measure online ad effectiveness, McKinley says Vizu was the obvious choice, since it's the leader in the field. Vizu's technology shows brief polls to people who have seen an ad, and others who haven't — so advertisers can use the polls to determine whether campaigns seem to improve people's perception of their company. McKinley says one of Vizu's big draws is the fact that it provides advertisers with real-time data, so that they can tweak campaigns based on the results.
Eventually, Nielsen will do more to integrate Vizu's features with its measurement of online ad reach, and with its cross-platform products. The goal, McKinley says, is "bringing data out of Vizu systems and connecting up with how we measure television, so we can offer advertisers a complete picture of reach and effectiveness across television and online."
Vizu raised more than $10 million in funding from investors including Ron Conway, Esther Dyson, Draper Fisher Jurvetson, iNovia Capital, and Greycroft Partners. The financial terms of the deal were not disclosed, but McKinley says the Vizu team will be joining Nielsen, and that it will continue working out of its San Francisco offices.


This jewellery box is made from the finest full hide black leather and is lined inside with soft simulated suede. It is a medium sized box with plenty of versatile storage. There are slotted sections for rings as well compartments for earrings and other accessories. One sections has a padded cushion perfect for a watch , bracelet or bangle. It has a fitted mirror inside the lid. It has a key lock to keep it closed and secure. A nice sized box with plenty of versatile storage. Perfect for a gift or personal use.


text:
U.S.S. Downes (1913)
Hull Number: DD-45
Builder: New York Shipbuilding[1]
Laid down: 27 Jun, 1912[2]
Launched: 8 Nov, 1913[3]
Commissioned: 11 Feb, 1915[4]
Decommissioned: 6 Jun, 1922[5]
Stricken: 5 Jul, 1934[6]
U.S.S. Downes was one of eight Cassin class destroyers completed for the U.S. Navy.
2 Captains
Downes was commissioned on 11 February, 1915 under the command of Lieutenant Commander Alfred W. Johnson.
Lieutenant Commander Alfred W. Johnson, 11 February, 1915
Lieutenant (Junior Grade) Joseph F. Crowell, Jr., before 1 January, 1917[7]
Commander Alexander Sharp, Jr., 23 June, 1918[8]
Lieutenant Commander Thomas S. McCloy, 15 August, 1921[9]
↑ Friedman. U.S. Destroyers. p. 429.
↑ Register of Officers, 1917. p. 50.
↑ Register of Officers, 1919. pp. 30-31.
Cassin Class Destroyer
Cassin Cummings Downes Duncan
Aylwin Parker Benham Balch
<– Monaghan Class Destroyers (US) O'Brien Class –>
Retrieved from "http://www.dreadnoughtproject.org/tfs/index.php?title=U.S.S._Downes_(1913)&oldid=226878"
Small Vessel
Ship (US)
Small Vessel (US)
Destroyer (US)
Content is available under Attribution-NonCommercial-NoDerivs 2.5 unless otherwise noted.


Can someone suggest a PC build?
I NEED A SCREEN RECORDER FOR GAMING!
Where should I buy my PC Parts? And what should I get?
Does anyone play CS:GO? If you do look here!
CAR KEYS - Free One Key Driving Mayhem!
Guys Need Help With Name Please!!!!
PC anywhere from 500 to 700€?
What desktop should I get?


Are Unicorns In The Bible A Mythical Animal Or Something Else?
So what is the real answer? There are many who make fun of the bible who say it is all fantasy and they use unicorns as one example. Clearly they have not done the research and study on the subject. This video goes into an in depth bible study on the word unicorns mentioned in the scriptures. This study is very interesting and once again proves the validity of the bible.
I disagree with the end of video where the author says there is a mistake in the old King James bible, there is simply a difference in the translations.
Watch this interesting video and learn something new about God's word today. Enjoy!


On January 15th, members of Volterra and IRIS met with Constantino Caminero Saldaña, head of the ITACyL Pest Area at their facilities in Valladolid, to present the work being done under LIFE Laser Fence. Constantino was very interested in the project and discussed the possibility of replicating Laser Fence in collaboration with ITACyL.
On January 12th, the members of Volterra met with Gonzalo Vidal de Vidar Soluciones Ambientales in Logroño to present the project Life Laser Fence. Gonzalo was very interested in the project and the possibilities offered by lasers to scare away animals from the crops in the possibility of replicating laser Fence in collaboration with Vidar.


Here are some links just to get some traffic going. Apparently it's important.
I've made a sketch show on YouTube called Blink to Think. The second series should be made sometime in the Autumn.
I don't go on my Facebook much.


text:
Mom who stabbed girl was investigated by CPS
News // Houston & Texas
Mother had been investigated by CPSWoman had past abuse allegations before stabbing her daughter and drowning herself
Mike Glenn, Copyright 2004 Houston Chronicle
Nov. 8, 2004 Updated: Aug. 14, 2011 1 a.m.
A northwest Harris County woman who stabbed her young daughter several times before drowning herself in a retention pond Saturday had been under investigation for a past child abuse allegation, officials said.
Darlene Bryant, 40, voluntarily surrendered custody of her 10-year-old daughter after the abuse allegation was reported to authorities in December 2003. Officials on Sunday said they could not release any details about the earlier incident.
"It was a violent incident that involved allegations of physical abuse," said Estella Olguin, Child Protective Services spokeswoman.
She said the agency has launched a new investigation stemming from Saturday's attack.
The girl, whose identity was not released, was sent to live with other relatives in the Houston area after the 2003 incident. Within the past three months, however, she had been allowed to visit her mother on weekends.
Bryant and her daughter had both been seeing therapists because of the past abuse allegations.
"Everyone who was seeing the child felt that she was safe," Olguin said. "Everyone is just shocked that this would happen."
The stabbing is the most recent violent incident between a child and parent in which an abuse allegation was involved. In August, a 10-year-old boy shot his father to death when he picked up the boy for a weekend visit. The boy's mother claimed he had been abused by his father.
In Saturday's incident, Bryant allegedly stabbed her daughter in the back several times about 4:30 p.m. while the two were spending the weekend together at her home in the 24000 block of Bar Kay in Hockley.
Detectives and child welfare advocates said they didn't know what triggered Saturday's attack. Olguin said they have no records of criminal charges filed against Bryant in the earlier incident.
The wounded girl managed to escape to a neighbor's home after the attack, investigators said.
She was taken by Life Flight helicopter to Memorial Hermann Hospital and was listed Sunday in stable condition.
The girl was alert and awake Sunday when a caseworker visited with her at the hospital.
"Her lung was punctured, (but) she should be released in the next few days," Olguin said.
Saturday's attack stunned Bryant's neighbors in the new subdivision in Hockley.
"I didn't know that she (Bryant) was in so much pain," said Swati Barman, who lives next door. "Some women are not capable of motherhood. Some women cannot take care of children."
After she stabbed her daughter, Bryant fled in a sport utility vehicle.
She drove for about two miles and parked next to a water retention pond near U.S. 290 West and Hager Road, investigators said.
Witnesses later told investigators they saw Bryant repeatedly forcing her head under the murky, knee-deep water. One person attempted to rescue the woman by jumping into the pond but was unable to reach her in time, Harris County sheriff's detectives said.
Waller County firefighters pulled Bryant's lifeless body from the water about 10:15 p.m. Officials said an autopsy will determine the cause of death.
Bryant lived alone and generally kept to herself, Barman said.
She said she occasionally saw adults at Bryant's home but never saw the woman's young daughter there.
mike.glenn@chron.com
Mike Glenn
Reach Mike on
Mike Glenn grew up in the Navy but enlisted in the Army after graduating from high school in Rockwall, Texas. Following his honorable discharge, Glenn attended the University of Texas at Arlington where he received a BA in History and a commission as a lieutenant in the Army. He led a platoon of cavalry troopers in combat during the Gulf War. Glenn spent about six years in the Army - both as an enlisted soldier and officer. He then studied journalism in graduate school and began his career in the news business. He has worked as a newspaper reporter in the Dallas area, El Paso, San Antonio and now in Houston with the Houston Chronicle. Glenn is married and has a daughter in college.


text:
Enabling Precision medicine for everyone: New pharmacogenomics solution launched in the US
Diana Georgi 27 February 2020
When it comes to precision medicine, it seems that pharmacogenomics (PGx) is an area where everyone could benefit. The study of PGx can determine how effective medications will be and determine the risk of adverse reactions such as stroke or arrhythmia.
Yesterday, MedImpact announced the launch of its new pharmacogenomics solution that reviews every prescribed drug for a patient against their genetic profile. MedImpact is the first pharmacy benefit manager (PBM) in the US to alert prescribers based on their genetic profile.
The PGx program is an industry-first solution that will protect patients from being prescribed ineffective or harmful drugs, which in turn reduces their risk of adverse events, improves their health and reduces waste.
Currently, the industry has struggled to implement pharmacogenomics to deliver actionable results to prescribers. Most PGx programs test how an individual will respond to a single therapy at any time, whereas the MedImpact solution screens for genetic interactions with more than 240 commonly prescribed medications and notifies prescribers when a potential gene-drug interaction exists.
The program was launched after a year-long pilot, where 65% of prescribers altered dosage or drug choices after being notified of a drug-gene interaction. Dale Brown, the President of MedImpact Healthcare Systems, stated that with the rising drug costs, personalised solutions are the future for sustainable healthcare in the US.
Clinical Genomics / Genetics / Genomics / Pharmacogenetics / Precision Medicine
Developing the NHS Genomic Medicine Service: Underpinning precision medicine
This talk was recorded at the Mathematical Institute, University of Oxford on 28th November 2019.…
Pharmacogenomics: Drugs, DNA and dosage
A medication that works for one person may not be as effective for others, or…
FDA releases list of evidence-based pharmacogenetic variants
Pharmacogenetics (PGx) is the study of how an individual's genetic makeup affects their drug response…


This email is to inform that we had to block your PayPal account because this ip 210.151.66.19 tryed to change the password of your account 3 times.We apologise for the inconvinience but the safety of your account is our main priority.
To remove the limitation login to your PayPal account!
Previous: Sorry, our records sho ... nded.Fresh ScamsNext: PayPal Security Measures.
This Email with the Subject "User Agreement Violation (ID PP133320)" was received in one of Scamdex's honeypot email accounts on Wed, 01 Aug 2007 18:47:17 -0700 and has been classified as a Generic Scam Email. The sender shows as "service@paypal.com"<service@paypal.com>, although that address was probably spoofed. We recommend that you do not attempt to contact any persons or organizations referenced in this email, as you may expose yourself to scammers and, at the very least, you will be added to their email address lists for spam purposes.


text:
package com.google.ical.values;

/**
 * An instant in time.
 *
 * @author Neal Gafter
 */
public class DateTimeValueImpl
        extends DateValueImpl
        implements DateTimeValue {
    private final int hour, minute, second;

    public DateTimeValueImpl(int year, int month, int day,
                             int hour, int minute, int second) {
        super(year, month, day);
        this.hour = hour;
        this.minute = minute;
        this.second = second;
    }

    public int hour() {
        return hour;
    }

    public int minute() {
        return minute;
    }

    public int second() {
        return second;
    }

    @Override
    public int hashCode() {
        return super.hashCode() ^
                ((this.hour << 12) + (this.minute << 6) + this.second);
    }

    @Override
    public String toString() {
        return String.format("%sT%02d%02d%02d",
                super.toString(),
                hour, minute, second);
    }
}


Discussion in 'Online Casinos' started by Black21Jack, Sep 22, 2004.
1. Is there a big difference between MG fun mode and real play?
2. Does the expert mode autoplay feature use perfect basic strategy? I looked for Vegas Downtown Blackjack at Wizard Of Odds and could not find any strategy for it. Is this just regular BJ?
3. Has anyone played Maple Casino? and if so what is their payout times like? Are they reputable?
Played there & lost my deposit but from what I've heard apart from some problems in the first few days of opening they're reputable & pay out ok - it's the same group as SunVegas & co. isn't it?
The autoplay has errors in it for all types of BJ :icon_evil - things like hitting on 9-9 in situations where you can't split them (so slightly hidden away from the unsuspecting player). I'm not sure about downtown BJ, but Vegas Strip has the lowest house edge & is given at Wiz of Odds. You should definitely edit the strategy tables... (check out 6-6, 7-7 & soft & hard 18, as far as I remember).
Not sure if it plays any differently in play/real - wouldn't have thought so but haven't played much in play mode. There seems to be a tendency to regularly get extreme swings, though the speed of the autoplay might make them seem worse than they are.
As for payouts - I made a cash withdrawal from them and it took about two days, which is about the norm for this group.
Can British pound players also get the extra money or is it only for US$ players? Same question about Sun Vegas.
I tried Maple Casino a couple weeks ago. Came out a little ahead and cashout was within 3 days.
Overall was a good experience for me.
Not sure about Downtown Blackjack. I know the Vegas Strip which offers the best odds need just a couple tweaks to be perfect strat.
I know Hit pair 7 vs 8 and pair 6 vs 7 are two then there is another but It slipped my mind and all my notes are so dissorganized cant find it right now!.
Thanks for the info guys. Just one more quick question regarding Microgaming, do these casinos require fax back identification documents like RTG does. I don't mind sending these in but one less hassle is great. If they don't require them then I think I will become a born again Microgamer, I love how fast the play is when set to fastest and 0 seconds between hands in expert mode autoplay.
I have cashed out at three Microgamming casinos. Luckey Nugget, The Gaming Club and Maple. None have required any faxing of documents or anthing. I did use Neteller not sure if that has anything to do with it.
It's restricted to USD, CAD, and Euros. Sorry!
I know the Vegas Strip which offers the best odds need just a couple tweaks to be perfect strat.
Just wondering if playing off perfect strategy, like the slight errors that are in the autoplay strategy chart would significantly increase the house edge. I play perfect strategy but I am not up on all the numbers, odds, and mathematics involved in the game. The reason I ask is because a friend of mine was playing the Vegas Strip BJ game without making the appropriate changes and lost his entire deposit in one session. We both were wondering if that would have made the difference. I know it is hard to tell without seeing his logs, and how many hands were dealt etc. but an idea of how improper strategy affects the odds would be helpful.
Strange, since I got the Casinomeister extra bonus in pounds! I busted out though so it didn't help. Also, they asked me for verification documents as soon as I opened the account but I don't think they normally do this.
I guess no one knows the answer to the above.
It is not that difficult to calculate. I did it once, and as I recall, the increase in the house edge is only 0.01% or 0.02%.
I just downloaded the new viper version of Fortune Room. Their auto play for two deck European BJ was an exact match with The Wiz's chart. So I see no problem! They now also have the single deck. Hope that BS is equivalent to the old micro pre viper single deck.


text:
SUPERMAN IS NOW BISEXUAL: WHY IS THIS IMPORTANT FOR OUR CHILDREN TO KNOW?
Jonathan Kent, the new iteration of Superman, is bisexual, according to DC Comics.
The traditionally heterosexual superhero will embark on a same-sex relationship with a friend in a new comic. Kent, who is the son of Clark Kent and Lois Lane, started his tenure in July.
"The idea of replacing Clark Kent with another straight white savior felt like a missed opportunity," Tom Taylor, the series writer, said in an interview with the New York Times.
His new love interest is Jay Nakamura, a reporter who cares for him after he "mentally and physically burns out from trying to save everyone that he can" in an issue of Superman: Son of Kal-El #5, to be released in November. Nakamura is also revealed to have special powers.
Kent's sexuality is not the only way in which the character has been updated for a new audience and time. Recent issues have seen him protesting against the deportation of refugees, stopping a high school shooting and trying to put out wildfires that were the cause of the climate crisis.
"I've always said everyone needs heroes and everyone deserves to see themselves in their heroes and I'm very grateful DC and Warner Bros share this idea," said Taylor in a statement. "Superman's symbol has always stood for hope, for truth and for justice. Today, that symbol represents something more. Today, more people can see themselves in the most powerful superhero in comics."
The news follows other recent attempts to add queerness to the world of comics. In August, it was announced that the latest version of Robin would have a boyfriend while in March, Marvel also made the decision to pass the mantle of Captain America to a gay character.
But the big-screen worlds of Marvel and DC remain less progressive. Tessa Thompson's character in Thor: Ragnarok was only revealed as bisexual in a tweet while Deadpool's sexual fluidity has yet to be fully explored. This November's Eternals is set to change things with the Marvel Cinematic Universe's first LGBTQ+ kiss between Brian Tyree Henry's Phastos, the first openly gay superhero in a Marvel movie, and Haaz Sleiman, who plays his husband.
Previous : NEO MOTIVATES US TO LIVING A FASTING FOCUSED LIFESTYLE TO ACHIEVE OPTIMAL HEALTH & LONGEVITY!
Next : SUICIDE AMONG BLACK GIRLS IS A MENTAL HEALTH CRISIS HIDING IN PLAIN SIGHT!


text:
WALE William
Posted: September 1st, 2012
William Henry Wale, beloved husband of Carol of Claresholm, passed away, surrounded by loved ones, on Wednesday, August 29, 2012 at the age of 59 years.
Besides his loving wife Carol, Bill will be remembered by his four step children, Corey (Chris), Mindy (James), Jason (Amanda) and Larry (Steph); grandchildren, Em, Haylee, Kee-ana, Wyatt, Kyla, Chase, Cedie and Hayden as well as cousins, Tammy (Jim) Jensen and son Tyler, and Vanessa (Shane) Koshney and their children, Ryan and Dan. Bill will also be remembered by family in England, Aunt Betty; cousins, Linda, Margaret and families and Richard and Stephanie Lord and sons, Michael (Nicole) and David. He was predeceased by his parents William and Elizabeth (Maude), and cousins, Geoff and Jessie Godley.
Bill came to Canada in 1977 and worked at the Claresholm Care Centre as a papered Chef. He later worked at Spyhill, Grand Cache and the Lethbridge Correctional Centre, where he was promoted to Deputy Director of Operations. Bill was involved with government services for thirty-five years. He also served as President of the Royal Canadian Legion, Branch #41 from 1998 to 1999, 2001 to 2002 and 2011 to 2012. His greatest passion was going to Las Vegas and playing darts.
Funeral Service will be held at LEYDEN'S CHAPEL OF REMEMBRANCE (4079 1st Street West, Claresholm) on Wednesday, September 5, 2012 at 2:00 P.M. Interment to follow at Claresholm Cemetery. If friends so desire, memorial donations may be made to the Canadian Cancer Society, Tel: (403) 205-3966, www.cancer.ca .
Condolences may be forwarded to the family by visiting www.leydens.com . Arrangements entrusted to LEYDEN'S FUNERAL HOME, Claresholm. Tel: 403-625-3212.


CSMCRI Recruitment 2019 - CSMCRI invites applications for recruitment of 01 Project Assistant Level II Posts. Form through Official Website www.narfbr.org. The applicants are requested to Download Application Form through Official Website www.csmcri.org. Interested candidates are requested to peruse the advertisement regarding the process of Examinations and Interview, Eligibility Criteria, Application Fee, How to Apply, Pattern of Examination, Syllabus, Question Paper, Admit Date, Exam Date, Result Date etc,. Refer thoroughly before applying.
CSMCRI may follow the following process to select the candidates.


Comminution circuit with Crushing, SAG mill, Screening, Ball mill and Cyclone. Process . In the grinding section, there is a SAG mill in a closed circuit with +10mm screening (aperture .
mineral processing screening solutions ball mill offers 132 ball mill trommel screen products. About 43% of these . Best using ball mill for grinding in copper ore processing line. Add to Compare. Quotation More. Grinding Mills For Sale In Zimbabwe Wet Type Continuous Ball Mill .


I was wrong in my last column, "Electoral cynicism and the curse of nane nane" (August 17). Raila Odinga's opposition National Super Alliance has not allowed Kenyans to "accept and move on" after the elections — despite initially telling the nation that the party would not contest the results. So Kenya and the world will only know what will be on September 1.
Although it may appear that the Alliance party prevaricated on its stated plan, the reason for doing so seems, interestingly, valid.
On August 14, the NGO Co-ordination Board, the oversight body for nongovernmental organisations, announced that a leading human rights organisation, the Kenyan Human Rights Commission, had been deregistered, allegedly for tax evasion, illegal bank accounts and illegally hiring experts. The next day the board tried to shut down another human rights organisation, Africa Centre for Open Governance, allegedly for "operating illegally".
Both organisations had been preparing to take the Electoral and Boundaries Commission (IEBC) to court for election malpractices. The acting interior Cabinet secretary, in an act of benevolence, suspended their deregistration for 90 days.
But this attempt to erase civil liberties with intimidation was worrying enough for the Alliance party to contest the electoral results before the week's deadline as required by law. After all, few could be sure that the two organisations would not again be banned and thus make it difficult to take the case to court.
In its petition to the court, the Alliance party requested that the election results be nullified. The crux of the case is that the results were announced by an IEBC server without clarity of where they originated; that some numbers on the forms differed from what had been gathered on the ground, allegedly by some crooked presiding officers; and that state officers and funds were used by the incumbent president, Uhuru Kenyatta, to campaign for the elections.
To this end, the Alliance party requested access to the IEBC server, apparently to show that it had been tampered with and that the results do not match those received at polling stations.
My friends and I were surprised when the courts granted the party access, overseen by the registrar of the supreme court, even though it was read-only access. What this means is, if the IEBC and the president-elect are right and Kenyatta won fairly, the court will have given the Alliance party enough rope to hang itself. If, on the other hand, the Alliance is right and there were irregularities in the way the elections were conducted, Kenya may end up having fresh elections within 60 days after the ruling.
Interestingly, the IEBC is not saying that everything went swimmingly with the elections. As in the Oscar Pistorius murder case that gave many lay people the Latin phrase dolus eventualis, this case, whatever happens, will also leave us with a phrase — one on which the IEBC's defence is resting. De minimis non curat lex, which my lawyer friend Jack translated as meaning "of small things, the law knows no cure". Essentially then, the IEBC is telling the court that, although there may have been problems, they were so small that they have not affected the outcome of the elections — Kenyatta is the winner.
Kenyatta's supporters say that, because the country is already in debt, new elections would be an unnecessary and costly exercise. Alliance supporters, on the other hand, argue that justice and democracy cannot be given a monetary value. They further argue that allowing the results of a flawed election to hold will mean a continuation of the impunity that has plagued Kenya with each electoral season, notably in 2007, with disastrous results.
It could mean that people like the United States' John Kerry and South Africa's Thabo Mbeki, who were election observers and seemed to push the opposition to accept the results even before the final tallying, will lose what credibility they still have left with the people of Kenya. It could also mean the IEBC will have to be more transparent in the way it conducts elections in the future — which would be a win for any future elections contenders in Kenya. Finally, a positive result for the Alliance party could mean fewer threats to civil society organisations and less erasure of civil liberties.
If, on the other hand, the courts rule against holding new elections, an outcome that seems more likely, there shall be a swearing-in ceremony for Kenyatta and Kenya will go back to business as usual, we hope.
As important as the case is, there has not been a shortage of comic relief. A purported pan-Africanist and former corruption czar is one of the lawyers defending the IEBC. He has worn one of those ghastly white wigs that even the seven judges have discarded.
And I could not help pointing out the irony that this lawyer, a self-confessed plagiarist — he was found guilty earlier in the year of "borrowing" about 5 000 words in his 10 000-word article from another lawyer — is representing the IEBC, which may not have been impartial and may have stolen votes for one of the candidates. It is almost as though the IEBC boss who appointed him wants to lose the case so that there can be a re-election.


Guns N' Roses is an American hard rock band from Los Angeles formed in 1985. The classic lineup, as signed to Geffen Records in 1986, consisted of vocalist Axl Rose, lead guitarist Slash, rhythm guitarist Izzy Stradlin, bassist Duff McKagan, and drummer Steven Adler. Apart from hard rock they are also associated with heavy metal.
They are best known for their album 'Appetite for Destruction' and songs like 'Sweet Child O' Mine'. Guns N' Roses has been credited with reviving the mainstream popularity of rock music, at a time when popular music was dominated by dance music and glam metal. Its late 1980s and early 1990s years have been described as the period in which the group brought forth a "hedonistic rebelliousness" reminiscent of the early Rolling Stones, a reputation that had earned the group the nickname "the most dangerous band in the world". The band's classic lineup, along with later members Reed and drummer Matt Sorum, was inducted into the Rock and Roll Hall of Fame in 2012, in its first year of eligibility.


The Forth: Boutique event venue in the heart of Toronto.
Located at 629 Danforth Avenue, The Forth is home to an 8000 sq. ft. grandiose venue, perfect for private or non-private events. Offering elevator service between floors, our luxurious three-story venue offers first-class views of the beautiful Danforth, a nice change in scenery from Toronto's bustling city core.
Guests wishing to host an event have exclusive access to the entire venue including the second floor dining room and third floor cocktail lounge.


Is working on Sunday a sin? The Bible says so. Is blogging? The Bible doesn't say. Here's a post from March 2011 about the topic. I don't know whether it's a true sin or not, but I don't think you or I should do any today. Just to be safe.
I know real men who do real work in factories and if the boss says so they do it on Sundays for time and a half. These men sneer at me when they here me talk about work. They no more think writing is work than, say, butterfly collecting.
Each of those chores fits my definition of real work because I detest doing them and can't do any of it while sitting zombie-like on the couch and watching sports.