diff options
Diffstat (limited to 'setup.py')
-rw-r--r-- | setup.py | 317 |
1 files changed, 215 insertions, 102 deletions
@@ -1,17 +1,23 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- -# pycryptopp -- Python wrappers for Crypto++ -# -# Copyright (C) 2009-2010 Zooko Wilcox-O'Hearn +# Copyright © 2009-2012 Zooko Wilcox-O'Hearn # Author: Zooko Wilcox-O'Hearn -# See README.txt for licensing information. +# +# See README.rst for licensing information. -import glob, os, platform, re, subprocess, sys +import os, platform, re, subprocess, sys -egg = os.path.realpath(glob.glob('darcsver-*.egg')[0]) -sys.path.insert(0, egg) +from setuptools import Extension, setup +from setuptools import Command +from distutils.util import get_platform +from setuptools.command.test import ScanningLoader +import unittest -from setuptools import Extension, find_packages, setup +PKG='pycryptopp' +VERSION_PY_FNAME = os.path.join('src', PKG, '_version.py') + +import versioneer # ECDSA=False ECDSA=True @@ -33,12 +39,13 @@ if "--disable-embedded-cryptopp" in sys.argv: if os.environ.get('PYCRYPTOPP_DISABLE_EMBEDDED_CRYPTOPP') == "1": DISABLE_EMBEDDED_CRYPTOPP=True -EMBEDDED_CRYPTOPP_DIR='embeddedcryptopp' +EMBEDDED_CRYPTOPP_DIR='src-cryptopp' -TEST_DOUBLE_LOAD=False -if "--test-double-load" in sys.argv: - TEST_DOUBLE_LOAD=True - sys.argv.remove("--test-double-load") +BUILD_DOUBLE_LOAD_TESTER=False +BDLTARG="--build-double-load-tester" +if BDLTARG in sys.argv: + BUILD_DOUBLE_LOAD_TESTER=True + sys.argv.remove(BDLTARG) # There are two ways that this setup.py script can build pycryptopp, either by using the # Crypto++ source code bundled in the pycryptopp source tree, or by linking to a copy of the @@ -161,7 +168,7 @@ else: trove_classifiers=[ "Environment :: Console", - "License :: OSI Approved :: GNU General Public License (GPL)", + "License :: OSI Approved :: GNU General Public License (GPL)", # See README.rst for alternative licensing. "License :: DFSG approved", "License :: Other/Proprietary License", "Intended Audience :: Developers", @@ -176,38 +183,39 @@ trove_classifiers=[ "Programming Language :: Python :: 2.4", "Programming Language :: Python :: 2.5", "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", "Topic :: Software Development :: Libraries", ] -PKG='pycryptopp' -VERSIONFILE = os.path.join(PKG, "_version.py") -verstr = "unknown" -try: - verstrline = open(VERSIONFILE, "rt").read() -except EnvironmentError: - pass # Okay, there is no version file. -else: - VSRE = r"^verstr = ['\"]([^'\"]*)['\"]" - mo = re.search(VSRE, verstrline, re.M) - if mo: - verstr = mo.group(1) - else: - print "unable to find version in %s" % (VERSIONFILE,) - raise RuntimeError("if %s.py exists, it is required to be well-formed" % (VERSIONFILE,)) - -srcs = ['pycryptopp/_pycryptoppmodule.cpp', 'pycryptopp/publickey/rsamodule.cpp', 'pycryptopp/hash/sha256module.cpp', 'pycryptopp/cipher/aesmodule.cpp'] +srcs = ['src/pycryptopp/_pycryptoppmodule.cpp', + 'src/pycryptopp/publickey/rsamodule.cpp', + 'src/pycryptopp/hash/sha256module.cpp', + 'src/pycryptopp/cipher/aesmodule.cpp', + 'src/pycryptopp/cipher/xsalsa20module.cpp', + ] if ECDSA: - srcs.append('pycryptopp/publickey/ecdsamodule.cpp') -if TEST_DOUBLE_LOAD: - srcs.append('_testdoubleloadmodule.cpp', ) + srcs.append('src/pycryptopp/publickey/ecdsamodule.cpp') +if BUILD_DOUBLE_LOAD_TESTER: + srcs.append('_doubleloadtester.cpp', ) ext_modules.append( Extension('pycryptopp._pycryptopp', extra_srcs + srcs, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries, extra_link_args=extra_link_args, extra_compile_args=extra_compile_args, define_macros=define_macros, undef_macros=undef_macros) ) -if TEST_DOUBLE_LOAD: +# python-ed25519 +sources = [os.path.join("src-ed25519","glue","ed25519module.c")] +sources.extend([os.path.join("src-ed25519","supercop-ref",s) + for s in os.listdir(os.path.join("src-ed25519","supercop-ref")) + if s.endswith(".c") and s!="test.c"]) +m = Extension("pycryptopp.publickey.ed25519._ed25519", + include_dirs=[os.path.join("src-ed25519","supercop-ref")], + sources=sources) +ext_modules.append(m) + + +if BUILD_DOUBLE_LOAD_TESTER: ext_modules.append( - Extension('_testdoubleload', extra_srcs + srcs, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries, extra_link_args=extra_link_args, extra_compile_args=extra_compile_args, define_macros=define_macros, undef_macros=undef_macros) + Extension('_doubleloadtester', extra_srcs + srcs, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries, extra_link_args=extra_link_args, extra_compile_args=extra_compile_args, define_macros=define_macros, undef_macros=undef_macros) ) miscdeps=os.path.join(os.getcwd(), 'misc', 'dependencies') @@ -215,102 +223,208 @@ dependency_links=[os.path.join(miscdeps, t) for t in os.listdir(miscdeps) if t.e setup_requires = [] install_requires = ['setuptools >= 0.6a9'] # for pkg_resources for loading test vectors for unit tests -# The darcsver command from the darcsver plugin is needed to initialize the -# distribution's .version attribute. (It does this either by examining darcs -# history, or if that fails by reading the pycryptopp/_version.py -# file). darcsver will also write a new version stamp in -# pycryptopp/_version.py, with a version number derived from darcs -# history. Note that the setup.cfg file has an "[aliases]" section which -# enumerates commands that you might run and specifies that it will run -# darcsver before each one. If you add different commands (or if I forgot some -# that are already in use), you may need to add it to setup.cfg and configure -# it to run darcsver before your command, if you want the version number to be -# correct when that command runs. http://pypi.python.org/pypi/darcsver -setup_requires.append('darcsver >= 1.6.3') - # setuptools_pyflakes is needed only if you want "./setup.py flakes" to run # pyflakes on all the pycryptopp modules. if 'flakes' in sys.argv[1:]: setup_requires.append('setuptools_pyflakes >= 1.0.0') -# setuptools_darcs is required to produce complete distributions (such -# as with "sdist" or "bdist_egg"), unless there is a -# pycryptopp.egg-info/SOURCE.txt file present which contains a complete -# list of files that should be included. -# http://pypi.python.org/pypi/setuptools_darcs However, requiring it -# runs afoul of a bug in Distribute, which was shipped in Ubuntu -# Lucid, so for now you have to manually install it before building -# sdists or eggs: -# http://bitbucket.org/tarek/distribute/issue/55/revision-control-plugin-automatically-installed-as-a-build-dependency-is-not-present-when-another-build-dependency-is-being -if False: - setup_requires.append('setuptools_darcs >= 1.1.0') - # stdeb is required to produce Debian files with "sdist_dsc". # http://github.com/astraw/stdeb/tree/master if "sdist_dsc" in sys.argv: setup_requires.append('stdeb') -data_fnames=['COPYING.GPL', 'COPYING.TGPPL.html', 'README.txt'] +data_fnames=['COPYING.GPL', 'COPYING.TGPPL.html', 'README.rst'] + +readmetext = open('README.rst').read() # In case we are building for a .deb with stdeb's sdist_dsc command, we put the # docs in "share/doc/pycryptopp". doc_loc = "share/doc/" + PKG data_files = [(doc_loc, data_fnames)] -# Note that due to a bug in distutils we also have to maintain a -# MANIFEST.in file specifying embeddedcryptopp/extraversion.h. This bug was -# fixed in Python 2.7 -data_files.append((EMBEDDED_CRYPTOPP_DIR, [EMBEDDED_CRYPTOPP_DIR+'/extraversion.h'])) +commands = {} -if ECDSA: - long_description='RSA-PSS-SHA256 signatures, ECDSA(1363)/EMSA1(SHA-256) signatures, SHA-256 hashes, and AES-CTR encryption' -else: - long_description='RSA-PSS-SHA256 signatures, SHA-256 hashes, and AES-CTR encryption' +###### Version updating code -PY_VERSION_BODY=''' -# This is the version of this tree, as created by %(versiontool)s from the darcs patch -# information: the main version number is taken from the most recent release -# tag. If some patches have been added since the last release, this will have a -# -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see -# pyutil.version_class for a description of what the different fields mean. +CPP_GIT_VERSION_BODY = ''' +/* This _version.py is generated from git metadata by the pycryptopp + * setup.py. The main version number is taken from the most recent release + * tag. If some patches have been added since the last release, this will + * have a -NN "build number" suffix, or else a -rNN "revision number" suffix. + */ -__pkgname__ = "%(pkgname)s" -verstr = "%(pkgversion)s" -try: - from pyutil.version_class import Version as pyutil_Version - __version__ = pyutil_Version(verstr) -except (ImportError, ValueError): - # Maybe there is no pyutil installed, or this may be an older version of - # pyutil.version_class which does not support SVN-alike revision numbers. - from distutils.version import LooseVersion as distutils_Version - __version__ = distutils_Version(verstr) +#define CRYPTOPP_EXTRA_VERSION "%(pkgname)s-%(pkgversion)s" ''' -CPP_VERSION_BODY=''' -/* This is the version of this tree, as created by %(versiontool)s from the darcs patch - * information: the main version number is taken from the most recent release - * tag. If some patches have been added since the last release, this will have a - * -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see - * pyutil.version_class for a description of what the different fields mean. - */ +def get_normalized_version(versions): + pieces = versions['version'].split("-") + +# examples: versions: {'version': '2.3.4-dirty', 'full': '5ebdca46cf83a185710ecb9b29d46ec8ac70de61-dirty'} +# examples versions: {'version': '0.5.29-108-g5ebdca4-dirty', 'full': '5ebdca46cf83a185710ecb9b29d46ec8ac70de61-dirty'} +# examples: pieces: ['0.5.29', '108', 'g5ebdca4', 'dirty'] +# examples: pieces: ['2.3.4', 'dirty'] +# examples: pieces: ['2.3.4'] + + normalized_version = [] + normalized_version.append(pieces.pop(0)) + + postrelease = None + dirty = False + + while len(pieces) > 0: + nextpiece = pieces.pop(0) + if re.match('\d+$', nextpiece): + postrelease = nextpiece + normalized_version.append('.'+postrelease) + elif nextpiece.startswith('g'): + continue + # Use the full version instead ,below + elif nextpiece == 'dirty': + dirty = True + + fullvhex = versions['full'].split('-')[0] + full = int(fullvhex, 16) + normalized_version.append('.'+str(full)) + + if postrelease is not None: + normalized_version.append('.post'+postrelease) + if dirty is True: + normalized_version.append('.dev0') + + return ''.join(normalized_version) + +def read_version_py(infname): + try: + verstrline = open(infname, "rt").read() + except EnvironmentError: + return None + else: + VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]" + mo = re.search(VSRE, verstrline, re.M) + if mo: + return mo.group(1) -#define CRYPTOPP_EXTRA_VERSION "%(pkgname)s-%(pkgversion)s" +EXTRAVERSION_H_FNAME = os.path.join(EMBEDDED_CRYPTOPP_DIR, 'extraversion.h') + +VERSION_BODY = ''' +# This is the version of this tree, as created by %(versiontool)s from the +# git information: the main version number is taken from the most recent +# release tag. If some patches have been added since the last release, this +# will have a -NN "build number" suffix, followed by -gXXX "revid" suffix. + +__pkgname__ = "%(pkgname)s" +__version__ = "%(pkgversion)s" ''' +class UpdateVersion(object): + def run(self): + + versions = versioneer.versions_from_vcs(PKG+'-', '.') + assert isinstance(versions, dict) + + vers_f_file = read_version_py(VERSION_PY_FNAME) + + if not versions and vers_f_file is None: + raise Exception("problem: couldn't get version information from revision control history, and there is no version information in '%s'. Stopping." % (VERSION_PY_FNAME,)) + + if versions: + version = get_normalized_version(versions) + else: + version = vers_f_file + + # Let's avoid touching the change time (ctime) on the files unless + # they actually need to be updated. + + if self.read_extraversion_h(EXTRAVERSION_H_FNAME) != version: + self.write_extraversion_h( + PKG, + version, + EXTRAVERSION_H_FNAME, + CPP_GIT_VERSION_BODY + ) + + if read_version_py(VERSION_PY_FNAME) != version: + self.write_version_py( + PKG, + version, + VERSION_PY_FNAME, + VERSION_BODY, + "pycryptopp's setup.py" + ) + + return version + + def write_version_py(self, pkgname, version, outfname, body, EXE_NAME): + f = open(outfname, "wb+") + f.write(body % { + 'versiontool': EXE_NAME, + 'pkgversion': version, + 'pkgname': pkgname, + }) + f.close() + + def write_extraversion_h(self, pkgname, version, outfname, body): + f = open(outfname, "wb") + f.write(body % {"pkgname": pkgname, "pkgversion": version}) + f.close() + + def read_extraversion_h(self, infname): + try: + verstrline = open(infname, "rt").read() + except EnvironmentError: + return None + else: + VSRE = r"^#define CRYPTOPP_EXTRA_VERSION +\"([^\"]*)\"" + mo = re.search(VSRE, verstrline, re.M) + if mo: + return mo.group(1) + +version = UpdateVersion().run() + +class Test(Command): + description = "run tests" + user_options = [] + def initialize_options(self): + self.test_suite = None + def finalize_options(self): + if self.test_suite is None: + self.test_suite = self.distribution.test_suite + def setup_path(self): + # copied from distutils/command/build.py + self.plat_name = get_platform() + plat_specifier = ".%s-%s" % (self.plat_name, sys.version[0:3]) + self.build_lib = os.path.join("build", "lib"+plat_specifier) + sys.path.insert(0, self.build_lib) + def run(self): + self.setup_path() + loader = ScanningLoader() + test = loader.loadTestsFromName(self.test_suite) + runner = unittest.TextTestRunner(verbosity=2) + result = runner.run(test) + sys.exit(not result.wasSuccessful()) +commands["test"] = Test + setup(name=PKG, - version=verstr, + version=version, description='Python wrappers for a few algorithms from the Crypto++ library', - long_description=long_description, - author='Zooko O\'Whielacronx', + long_description=readmetext, + author='Zooko Wilcox-O\'Hearn', author_email='zooko@zooko.com', - url='http://tahoe-lafs.org/trac/' + PKG, - license='GNU GPL', # see README.txt for details -- there is also an alternative licence - packages=find_packages(), + url='https://tahoe-lafs.org/trac/' + PKG, + license='GNU GPL', # see README.rst for details -- there is also an alternative licence + packages=["pycryptopp", + "pycryptopp.cipher", + "pycryptopp.hash", + "pycryptopp.publickey", + "pycryptopp.publickey.ed25519", + "pycryptopp.test", + ], include_package_data=True, exclude_package_data={ '': [ '*.cpp', '*.hpp', ] }, data_files=data_files, + package_dir={"pycryptopp": "src/pycryptopp"}, setup_requires=setup_requires, install_requires=install_requires, dependency_links=dependency_links, @@ -318,6 +432,5 @@ setup(name=PKG, ext_modules=ext_modules, test_suite=PKG+".test", zip_safe=False, # I prefer unzipped for easier access. - versionfiles=[os.path.join('pycryptopp', '_version.py'), os.path.join(EMBEDDED_CRYPTOPP_DIR, 'extraversion.h')], - versionbodies=[PY_VERSION_BODY, CPP_VERSION_BODY], + cmdclass=commands, ) |