Create asn1crypto_tests package, along with supporting tooling

Adds the following tasks:

 - python run.py build
 - python run.py version {pep440_version}

Tests may now be executed a number of different ways and will
automatically ensure the local copy of asn1crypto is used, if run from
a Git working copy, or archive of a working copy.

Versioning scheme switched from SemVer to PEP 440 since that is what
the Python ecosystem tooling supports.
diff --git a/setup.py b/setup.py
index 6a6d8c1..f4b6aba 100644
--- a/setup.py
+++ b/setup.py
@@ -1,9 +1,69 @@
+import codecs
 import os
 import shutil
+import sys
+import warnings
 
-from setuptools import setup, find_packages, Command
+import setuptools
+from setuptools import setup, Command
+from setuptools.command.egg_info import egg_info
 
-from asn1crypto import version
+
+PACKAGE_NAME = 'asn1crypto'
+PACKAGE_VERSION = '0.25.0.dev1'
+PACKAGE_ROOT = os.path.dirname(os.path.abspath(__file__))
+
+
+# setuptools 38.6.0 and newer know about long_description_content_type, but
+# distutils still complains about it, so silence the warning
+sv = setuptools.__version__
+svi = tuple(int(o) if o.isdigit() else o for o in sv.split('.'))
+if svi >= (38, 6):
+    warnings.filterwarnings(
+        'ignore',
+        "Unknown distribution option: 'long_description_content_type'",
+        module='distutils.dist'
+    )
+
+
+# Try to load the tests first from the source repository layout. If that
+# doesn't work, we assume this file is in the release package, and the tests
+# are part of the package {PACKAGE_NAME}_tests.
+if os.path.exists(os.path.join(PACKAGE_ROOT, 'tests')):
+    tests_require = []
+    test_suite = 'tests.make_suite'
+else:
+    tests_require = ['%s_tests' % PACKAGE_NAME]
+    test_suite = '%s_tests.make_suite' % PACKAGE_NAME
+
+
+# This allows us to send the LICENSE and docs when creating a sdist. Wheels
+# automatically include the LICENSE, and don't need the docs. For these
+# to be included, the command must be "python setup.py sdist".
+package_data = {}
+if sys.argv[1:] == ['sdist'] or sorted(sys.argv[1:]) == ['-q', 'sdist']:
+    package_data[PACKAGE_NAME] = [
+        '../LICENSE',
+        '../*.md',
+        '../docs/*.md',
+    ]
+
+
+# Ensures a copy of the LICENSE is included with the egg-info for
+# install and bdist_egg commands
+class EggInfoCommand(egg_info):
+    def run(self):
+        egg_info_path = os.path.join(
+            PACKAGE_ROOT,
+            '%s.egg-info' % PACKAGE_NAME
+        )
+        if not os.path.exists(egg_info_path):
+            os.mkdir(egg_info_path)
+        shutil.copy2(
+            os.path.join(PACKAGE_ROOT, 'LICENSE'),
+            os.path.join(egg_info_path, 'LICENSE')
+        )
+        egg_info.run(self)
 
 
 class CleanCommand(Command):
@@ -18,30 +78,38 @@
         pass
 
     def run(self):
-        folder = os.path.dirname(os.path.abspath(__file__))
-        for sub_folder in ['build', 'dist', 'asn1crypto.egg-info']:
-            full_path = os.path.join(folder, sub_folder)
+        sub_folders = ['build', 'temp', '%s.egg-info' % PACKAGE_NAME]
+        if self.all:
+            sub_folders.append('dist')
+        for sub_folder in sub_folders:
+            full_path = os.path.join(PACKAGE_ROOT, sub_folder)
             if os.path.exists(full_path):
                 shutil.rmtree(full_path)
-        for root, dirnames, filenames in os.walk(os.path.join(folder, 'asn1crypto')):
-            for filename in filenames:
+        for root, dirs, files in os.walk(os.path.join(PACKAGE_ROOT, PACKAGE_NAME)):
+            for filename in files:
                 if filename[-4:] == '.pyc':
                     os.unlink(os.path.join(root, filename))
-            for dirname in list(dirnames):
+            for dirname in list(dirs):
                 if dirname == '__pycache__':
                     shutil.rmtree(os.path.join(root, dirname))
 
 
+readme = ''
+with codecs.open(os.path.join(PACKAGE_ROOT, 'readme.md'), 'r', 'utf-8') as f:
+    readme = f.read()
+
+
 setup(
-    name='asn1crypto',
-    version=version.__version__,
+    name=PACKAGE_NAME,
+    version=PACKAGE_VERSION,
 
     description=(
         'Fast ASN.1 parser and serializer with definitions for private keys, '
         'public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, '
         'PKCS#12, PKCS#5, X.509 and TSP'
     ),
-    long_description='Docs for this project are maintained at https://github.com/wbond/asn1crypto#readme.',
+    long_description=readme,
+    long_description_content_type='text/markdown',
 
     url='https://github.com/wbond/asn1crypto',
 
@@ -76,11 +144,14 @@
 
     keywords='asn1 crypto pki x509 certificate rsa dsa ec dh',
 
-    packages=find_packages(exclude=['tests*', 'dev*']),
+    packages=[PACKAGE_NAME],
+    package_data=package_data,
 
-    test_suite='tests.make_suite',
+    tests_require=tests_require,
+    test_suite=test_suite,
 
     cmdclass={
         'clean': CleanCommand,
+        'egg_info': EggInfoCommand,
     }
 )