Distribution and installation

The new module setup.py handles creation of package distributions in
compressed formats, and performs installation of said distributions
after decompression. Distribution strategy for PyDTLS is in the form
of source distributions only.

Building the OpenSSL library on Windows is non-trivial. Requirements
include linking against the same version of the C runtime that is used
by the Python interpreter, or else Microsoft redistributable
installation may also need to be performed. For the convenience of
Windows users, the distribution procedure includes creation of
prebuilt versions of the OpenSSL library for both 32- and 64-bit
versions of Windows. Despite containing binaries, these are still
source distributions that are installed with "python setup.py
install."

A version of OpenSSL compiled with the MinGW toolchain is included.
cygcrypto-1.0.0.dll and cygssl-1.0.0.dll contain symbols and can be
debugged with gdb. All MinGW OpenSSL dll's link with msvcr90.dll.

In order to avoid making installation a requirement after cloning, the
package initializer looks for prebuilts of the currently executing
platform and copies them into the dtls package directory before
continuing module initialization.

A distribution containing prebuilts for all platforms as well as those
containing no prebuilts (appropriate for Linux) can be generated by
issuing "python setup.py sdist --prebuilts."
incoming
Ray Brown 2012-12-16 20:22:49 -08:00
parent 8800ffa238
commit 62f30a1888
13 changed files with 167 additions and 0 deletions

View File

@ -15,6 +15,29 @@ sockets.
wrap_socket's parameters and their semantics have been maintained. wrap_socket's parameters and their semantics have been maintained.
""" """
def _prep_bins():
"""
Support for running straight out of a cloned source directory instead
of an installed distribution
"""
from os import path
from sys import platform, maxsize
from shutil import copy
bit_suffix = "-x86_64" if maxsize > 2**32 else "-x86"
package_root = path.abspath(path.dirname(__file__))
prebuilt_path = path.join(package_root, "prebuilt", platform + bit_suffix)
config = {"MANIFEST_DIR": prebuilt_path}
try:
execfile(path.join(prebuilt_path, "manifest.pycfg"), config)
except IOError:
return # there are no prebuilts for this platform - nothing to do
files = map(lambda x: path.join(prebuilt_path, x), config["FILES"])
for prebuilt_file in files:
copy(path.join(prebuilt_path, prebuilt_file), package_root)
_prep_bins() # prepare before module imports
from patch import do_patch from patch import do_patch
from sslconnection import SSLConnection from sslconnection import SSLConnection
from demux import force_routing_demux, reset_default_demux from demux import force_routing_demux, reset_default_demux

View File

@ -0,0 +1,16 @@
# Prebuilt directory manifest. Written by Ray Brown.
# This file is executed by the distribution builder, as well as the dtls
# package startup code; the purpose of the latter is being able to run
# from a cloned source directory without executing any sort of installation
# procedure. This file provides the definitions required to create
# a distribution including this directory's prebuilts.
from os import path
from glob import glob
assert MANIFEST_DIR
ARCHITECTURE = "mingw-win32"
FORMATS = "gztar"
FILES = map(lambda x: path.basename(x),
glob(path.join(MANIFEST_DIR, "*.dll")))

Binary file not shown.

View File

@ -0,0 +1,16 @@
# Prebuilt directory manifest. Written by Ray Brown.
# This file is executed by the distribution builder, as well as the dtls
# package startup code; the purpose of the latter is being able to run
# from a cloned source directory without executing any sort of installation
# procedure. This file provides the definitions required to create
# a distribution including this directory's prebuilts.
from os import path
from glob import glob
assert MANIFEST_DIR
ARCHITECTURE = "win32"
FORMATS = "zip"
FILES = map(lambda x: path.basename(x),
glob(path.join(MANIFEST_DIR, "*.dll")))

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,16 @@
# Prebuilt directory manifest. Written by Ray Brown.
# This file is executed by the distribution builder, as well as the dtls
# package startup code; the purpose of the latter is being able to run
# from a cloned source directory without executing any sort of installation
# procedure. This file provides the definitions required to create
# a distribution including this directory's prebuilts.
from os import path
from glob import glob
assert MANIFEST_DIR
ARCHITECTURE = "win-amd64"
FORMATS = "zip"
FILES = map(lambda x: path.basename(x),
glob(path.join(MANIFEST_DIR, "*.dll")))

Binary file not shown.

96
setup.py 100644
View File

@ -0,0 +1,96 @@
#!/usr/bin/env python
# PyDTLS setup script. Written by Ray Brown.
"""PyDTLS setup script
Install or create a distribution of the PyDTLS package.
"""
from os import listdir, path, remove, rename
from sys import argv
from pickle import dump, load
from distutils.core import setup
from distutils.command.install import INSTALL_SCHEMES
# Make the root for data file installations the same as Python code
for scheme in INSTALL_SCHEMES.values():
scheme['data'] = scheme['purelib']
NAME = "Dtls"
VERSION = "0.1"
DIST_DIR = "dist"
FORMAT_TO_SUFFIX = { "zip": ".zip",
"gztar": ".tar.gz",
"bztar": ".tar.bz2",
"ztar": ".tar.Z",
"tar": ".tar" }
def invoke_setup(data_files=None):
data_files_file = "data_files"
data_files_file_created = False
try:
if data_files:
# Save the value of data_files with the distribution archive
data_files_file_created = True
with open(data_files_file, "wb") as fl:
dump(data_files, fl)
data_files.append(('', [data_files_file]),)
else:
# Load data_files from the distribution archive, if present
try:
with open(data_files_file, "rb") as fl:
data_files = load(fl)
except IOError:
pass
setup(name=NAME,
version=VERSION,
description="Python Datagram Transport Layer Security",
author="Ray Brown",
author_email="code@liquibits.com",
url="http://www.github.com/pydtls",
packages=["dtls", "dtls.demux", "dtls.test"],
package_data={"dtls.test": ["certs/*.pem"]},
data_files=data_files,
)
finally:
if data_files_file_created:
try:
remove(data_files_file)
except OSError:
pass
def make_dists():
prebuilt_platform_root = path.join("dtls", "prebuilt")
for platform in listdir(prebuilt_platform_root):
config = {"MANIFEST_DIR": path.join(prebuilt_platform_root, platform)}
execfile(path.join(prebuilt_platform_root, platform, "manifest.pycfg"),
config)
files = map(lambda x: "dtls/prebuilt/" + platform + "/" + x,
config["FILES"])
argv.append("--formats=" + config["FORMATS"])
invoke_setup([('dtls', files)])
del argv[-1]
for dist_format in config["FORMATS"].split(','):
source_name = path.join(DIST_DIR,
NAME + "-" + VERSION +
FORMAT_TO_SUFFIX[dist_format])
target_name = path.join(DIST_DIR,
NAME + "-" + VERSION +
".sdist_with_openssl." +
config["ARCHITECTURE"] +
FORMAT_TO_SUFFIX[dist_format])
try:
remove(target_name)
except OSError:
pass
rename(source_name, target_name)
# Finally the distribution without prebuilts
argv.append("--formats=zip,gztar")
invoke_setup()
if __name__ == "__main__":
if argv[-1] == "--prebuilts":
del argv[-1]
make_dists()
else:
invoke_setup()