Improve PyPI packaging (#71)

* Move files for better setup.py packaging

* Update setup.py and configs for src layout

* Run tests on setup.py build

In effect, this tests that the setup.py configuration is correct.

coverage combine and coverage:paths are added to keep the displayed
coverage paths as src/ssh_audit/*.py instead of
.tox/$envname/**/site-packages/ssh_audit/*.py

* Remove unnecessary encoding declarations

Python 3 defaults to UTF-8 encoding.
https://docs.python.org/3/reference/lexical_analysis.html#encoding-declarations

* Remove shebang from colorama type stubs

Shouldn't need to be an executable.
Related: git has this file tracked as chmod -x.
This commit is contained in:
Ganden Schaffner 2020-10-11 18:03:02 +00:00 committed by GitHub
parent 1b0446344c
commit b15664929f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 4034 additions and 4005 deletions

23
.gitignore vendored
View File

@ -1,5 +1,5 @@
*~
*.pyc
*.py[cod]
*.exe
*.asc
venv*/
@ -9,11 +9,16 @@ venv*/
.coverage*
reports/
.scannerwork/
packages/sshaudit/LICENSE
packages/sshaudit/README.md
packages/sshaudit/sshaudit.py
packages/parts/
packages/prime/
packages/snap/
packages/stage/
packages/ssh-audit_*.snap
# PyPI packaging
/build/
/dist/
*.egg-info/
*.egg
# Snap packaging
/parts/
/prime/
/snap/
/stage/
/ssh-audit_*.snap

11
Makefile.pypi Normal file
View File

@ -0,0 +1,11 @@
all:
python3 setup.py sdist bdist_wheel
uploadtest:
twine upload --repository-url https://test.pypi.org/legacy/ dist/*
uploadprod:
twine upload dist/*
clean:
rm -rf build/ dist/ src/*.egg-info/

View File

@ -7,7 +7,7 @@ $ virtualenv -p /usr/bin/python3 /tmp/pypi_upload
$ cd /tmp/pypi_upload; source bin/activate
$ pip3 install twine
$ cp -R path/to/ssh-audit .
$ cd ssh-audit/packages
$ cd ssh-audit
$ make -f Makefile.pypi
$ make -f Makefile.pypi uploadtest
@ -22,7 +22,7 @@ $ pip3 install --index-url https://test.pypi.org/simple ssh-audit
To upload to production server:
$ cd /tmp/pypi_upload; source bin/activate
$ cd ssh-audit/pypi
$ cd ssh-audit
$ make -f Makefile.pypi uploadprod

View File

@ -1 +0,0 @@
include sshaudit/LICENSE

View File

@ -1,14 +0,0 @@
all:
cp ../ssh-audit.py sshaudit/sshaudit.py
cp ../LICENSE sshaudit/LICENSE
cp ../README.md sshaudit/README.md
python3 setup.py sdist bdist_wheel
uploadtest:
twine upload --repository-url https://test.pypi.org/legacy/ dist/*
uploadprod:
twine upload dist/*
clean:
rm -rf parts/ prime/ snap/ stage/ build/ dist/ *.egg-info/ sshaudit/sshaudit.py sshaudit/LICENSE sshaudit/README.md ssh-audit*.snap

View File

@ -1,58 +0,0 @@
# -*- coding: utf-8 -*-
import re
import sys
from setuptools import setup
print_warning = False
m = re.search(r'^VERSION\s*=\s*\'v(\d\.\d\.\d)\'', open('sshaudit/sshaudit.py').read(), re.M)
if m is None:
# If we failed to parse the stable version, see if this is the development version.
m = re.search(r'^VERSION\s*=\s*\'v(\d\.\d\.\d-dev)\'', open('sshaudit/sshaudit.py').read(), re.M)
if m is None:
print("Error: could not parse VERSION variable from ssh-audit.py.")
sys.exit(1)
else: # Continue with the development version, but print a warning later.
print_warning = True
version = m.group(1)
print("\n\nPackaging ssh-audit v%s...\n\n" % version)
with open("sshaudit/README.md", "rb") as f:
long_descr = f.read().decode("utf-8")
setup(
name="ssh-audit",
packages=["sshaudit"],
license='MIT',
entry_points={
"console_scripts": ['ssh-audit = sshaudit.sshaudit:main']
},
version=version,
description="An SSH server & client configuration security auditing tool",
long_description=long_descr,
long_description_content_type="text/markdown",
author="Joe Testa",
author_email="jtesta@positronsecurity.com",
url="https://github.com/jtesta/ssh-audit",
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Information Technology",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Security",
"Topic :: Security :: Cryptography"
])
if print_warning:
print("\n\n !!! WARNING: development version detected (%s). Are you sure you want to package this version? Probably not...\n" % version)

View File

@ -1,4 +0,0 @@
# -*- coding: utf-8 -*-
from .sshaudit import main
main()

7
pyproject.toml Normal file
View File

@ -0,0 +1,7 @@
[build-system]
# https://pip.pypa.io/en/stable/reference/pip/#pep-517-and-518-support
requires = [
"setuptools>=40.8.0",
"wheel"
]
build-backend = "setuptools.build_meta"

44
setup.cfg Normal file
View File

@ -0,0 +1,44 @@
[metadata]
name = ssh-audit
version = attr: ssh_audit.ssh_audit.VERSION
author = Joe Testa
author_email = jtesta@positronsecurity.com
description = An SSH server & client configuration security auditing tool
long_description = file: README.md
long_description_content_type = text/markdown
license_file = LICENSE
url = https://github.com/jtesta/ssh-audit
project_urls =
Source Code = https://github.com/jtesta/ssh-audit
Bug Tracker = https://github.com/jtesta/ssh-audit/issues
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: MIT License
Operating System :: OS Independent
Programming Language :: Python :: 3
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: Implementation :: PyPy
Topic :: Security
Topic :: Security :: Cryptography
[options]
packages = find:
package_dir =
= src
python_requires = >=3.5,<4
[options.packages.find]
where = src
[options.package_data]
ssh_audit = policies/*
[options.entry_points]
console_scripts =
ssh-audit = ssh_audit.ssh_audit:main

23
setup.py Normal file
View File

@ -0,0 +1,23 @@
import re
import sys
from setuptools import setup
print_warning = False
m = re.search(r'^VERSION\s*=\s*\'v(\d\.\d\.\d)\'', open('src/ssh_audit/ssh_audit.py').read(), re.M)
if m is None:
# If we failed to parse the stable version, see if this is the development version.
m = re.search(r'^VERSION\s*=\s*\'v(\d\.\d\.\d-dev)\'', open('src/ssh_audit/ssh_audit.py').read(), re.M)
if m is None:
print("Error: could not parse VERSION variable from ssh_audit.py.")
sys.exit(1)
else: # Continue with the development version, but print a warning later.
print_warning = True
version = m.group(1)
print("\n\nPackaging ssh-audit v%s...\n\n" % version)
# see setup.cfg
setup()
if print_warning:
print("\n\n !!! WARNING: development version detected (%s). Are you sure you want to package this version? Probably not...\n" % version)

View File

@ -0,0 +1,2 @@
from ssh_audit.ssh_audit import main
main()

3912
src/ssh_audit/ssh_audit.py Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
import os
import io
import sys
import socket
@ -7,9 +6,8 @@ import pytest
@pytest.fixture(scope='module')
def ssh_audit():
__rdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
sys.path.append(os.path.abspath(__rdir))
return __import__('ssh-audit')
import ssh_audit.ssh_audit
return ssh_audit.ssh_audit
# pylint: disable=attribute-defined-outside-init

View File

@ -1,5 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Optional
def init(autoreset: bool = False, convert: Optional[bool] = None, strip: Optional[bool] = None, wrap: bool = True) -> None: ...

13
tox.ini
View File

@ -3,7 +3,6 @@ envlist =
py{py3}-{test,pylint,flake8,vulture}
py{35,36,37,38}-{test,mypy,pylint,flake8,vulture}
cov
skipsdist = true
skip_missing_interpreters = true
[testenv]
@ -16,13 +15,14 @@ deps =
py{py3,35,36,37,38}-{lint,flake8},lint: {[testenv:flake8]deps}
py{py3,35,36,37,38}-{lint,vulture},lint: {[testenv:vulture]deps}
setenv =
SSHAUDIT = {toxinidir}/ssh-audit.py
SSHAUDIT = {toxinidir}/src
test: COVERAGE_FILE = {toxinidir}/.coverage.{envname}
type,mypy: MYPYPATH = {toxinidir}/test/stubs
type,mypy: MYPYHTML = {toxinidir}/reports/html/mypy
commands =
test: coverage run --source ssh-audit -m -- \
test: coverage run --source ssh_audit -m -p -- \
test: pytest -v --junitxml={toxinidir}/reports/junit.{envname}.xml {posargs:test}
test: coverage combine
test: coverage report --show-missing
test: coverage html -d {toxinidir}/reports/html/coverage.{envname}
py{35,36,37,38}-{type,mypy}: {[testenv:mypy]commands}
@ -73,7 +73,7 @@ commands =
deps =
flake8
commands =
flake8 {posargs:{env:SSHAUDIT} {toxinidir}/packages/setup.py {toxinidir}/test} --statistics
flake8 {posargs:{env:SSHAUDIT} {toxinidir}/setup.py {toxinidir}/test {toxinidir}/ssh-audit.py} --statistics
[testenv:vulture]
deps =
@ -131,3 +131,8 @@ ignore =
[pytest]
junit_family = xunit1
[coverage:paths]
source =
src
*/site-packages

View File

@ -12,7 +12,9 @@ On a Windows machine, do the following:
3.) Create the executable with:
pyinstaller -D --icon packages\windows_icon.ico --add-data policies;policies ssh-audit.py
cd src\ssh_audit
rename ssh_audit.py ssh-audit.py
pyinstaller -D --icon ..\..\windows_icon.ico --add-data policies;policies ssh-audit.py
4.) Rename the "dist\ssh-audit\" folder to "dist\ssh-audit vX.X.X\"

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB