1import codecs
2import os
3import shutil
4import sys
5import warnings
6
7import setuptools
8from setuptools import setup, Command
9from setuptools.command.egg_info import egg_info
10
11
12PACKAGE_NAME = 'asn1crypto'
13PACKAGE_VERSION = '1.4.0'
14PACKAGE_ROOT = os.path.dirname(os.path.abspath(__file__))
15
16
17# setuptools 38.6.0 and newer know about long_description_content_type, but
18# distutils still complains about it, so silence the warning
19sv = setuptools.__version__
20svi = tuple(int(o) if o.isdigit() else o for o in sv.split('.'))
21if svi >= (38, 6):
22    warnings.filterwarnings(
23        'ignore',
24        "Unknown distribution option: 'long_description_content_type'",
25        module='distutils.dist'
26    )
27
28
29# Try to load the tests first from the source repository layout. If that
30# doesn't work, we assume this file is in the release package, and the tests
31# are part of the package {PACKAGE_NAME}_tests.
32if os.path.exists(os.path.join(PACKAGE_ROOT, 'tests')):
33    tests_require = []
34    test_suite = 'tests.make_suite'
35else:
36    tests_require = ['%s_tests' % PACKAGE_NAME]
37    test_suite = '%s_tests.make_suite' % PACKAGE_NAME
38
39
40# This allows us to send the LICENSE and docs when creating a sdist. Wheels
41# automatically include the LICENSE, and don't need the docs. For these
42# to be included, the command must be "python setup.py sdist".
43package_data = {}
44if sys.argv[1:] == ['sdist'] or sorted(sys.argv[1:]) == ['-q', 'sdist']:
45    package_data[PACKAGE_NAME] = [
46        '../LICENSE',
47        '../*.md',
48        '../docs/*.md',
49    ]
50
51
52# Ensures a copy of the LICENSE is included with the egg-info for
53# install and bdist_egg commands
54class EggInfoCommand(egg_info):
55    def run(self):
56        egg_info_path = os.path.join(
57            PACKAGE_ROOT,
58            '%s.egg-info' % PACKAGE_NAME
59        )
60        if not os.path.exists(egg_info_path):
61            os.mkdir(egg_info_path)
62        shutil.copy2(
63            os.path.join(PACKAGE_ROOT, 'LICENSE'),
64            os.path.join(egg_info_path, 'LICENSE')
65        )
66        egg_info.run(self)
67
68
69class CleanCommand(Command):
70    user_options = [
71        ('all', 'a', '(Compatibility with original clean command)'),
72    ]
73
74    def initialize_options(self):
75        self.all = False
76
77    def finalize_options(self):
78        pass
79
80    def run(self):
81        sub_folders = ['build', 'temp', '%s.egg-info' % PACKAGE_NAME]
82        if self.all:
83            sub_folders.append('dist')
84        for sub_folder in sub_folders:
85            full_path = os.path.join(PACKAGE_ROOT, sub_folder)
86            if os.path.exists(full_path):
87                shutil.rmtree(full_path)
88        for root, dirs, files in os.walk(os.path.join(PACKAGE_ROOT, PACKAGE_NAME)):
89            for filename in files:
90                if filename[-4:] == '.pyc':
91                    os.unlink(os.path.join(root, filename))
92            for dirname in list(dirs):
93                if dirname == '__pycache__':
94                    shutil.rmtree(os.path.join(root, dirname))
95
96
97readme = ''
98with codecs.open(os.path.join(PACKAGE_ROOT, 'readme.md'), 'r', 'utf-8') as f:
99    readme = f.read()
100
101
102setup(
103    name=PACKAGE_NAME,
104    version=PACKAGE_VERSION,
105
106    description=(
107        'Fast ASN.1 parser and serializer with definitions for private keys, '
108        'public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, '
109        'PKCS#12, PKCS#5, X.509 and TSP'
110    ),
111    long_description=readme,
112    long_description_content_type='text/markdown',
113
114    url='https://github.com/wbond/asn1crypto',
115
116    author='wbond',
117    author_email='will@wbond.net',
118
119    license='MIT',
120
121    classifiers=[
122        'Development Status :: 5 - Production/Stable',
123
124        'Intended Audience :: Developers',
125
126        'License :: OSI Approved :: MIT License',
127
128        'Programming Language :: Python',
129        'Programming Language :: Python :: 2',
130        'Programming Language :: Python :: 2.6',
131        'Programming Language :: Python :: 2.7',
132        'Programming Language :: Python :: 3',
133        'Programming Language :: Python :: 3.2',
134        'Programming Language :: Python :: 3.3',
135        'Programming Language :: Python :: 3.4',
136        'Programming Language :: Python :: 3.5',
137        'Programming Language :: Python :: 3.6',
138        'Programming Language :: Python :: 3.7',
139        'Programming Language :: Python :: 3.8',
140        'Programming Language :: Python :: Implementation :: CPython',
141        'Programming Language :: Python :: Implementation :: PyPy',
142
143        'Topic :: Security :: Cryptography',
144    ],
145
146    keywords='asn1 crypto pki x509 certificate rsa dsa ec dh',
147
148    packages=[PACKAGE_NAME],
149    package_data=package_data,
150
151    tests_require=tests_require,
152    test_suite=test_suite,
153
154    cmdclass={
155        'clean': CleanCommand,
156        'egg_info': EggInfoCommand,
157    }
158)
159