diff --git a/.github/workflows/test_docker.yml b/.github/workflows/test_docker.yml index 19b9efb3..bb8ec055 100644 --- a/.github/workflows/test_docker.yml +++ b/.github/workflows/test_docker.yml @@ -58,7 +58,7 @@ jobs: run: | add-apt-repository -y ppa:gift/dev apt-get update -q - apt-get install -y build-essential python3 python3-dev libbde-python3 libewf-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-cryptography python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pytsk3 python3-pyxattr python3-setuptools python3-yaml + apt-get install -y build-essential python3 python3-dev libbde-python3 libewf-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-cffi-backend python3-cryptography python3-dfdatetime python3-distutils python3-dtfabric python3-idna python3-pip python3-pytsk3 python3-pyxattr python3-setuptools python3-wheel python3-yaml - name: Run tests env: LANG: en_US.UTF-8 @@ -69,6 +69,9 @@ jobs: LANG: en_US.UTF-8 run: | if test -f tests/end-to-end.py; then PYTHONPATH=. python3 ./tests/end-to-end.py --debug -c config/end-to-end.ini; fi + - name: Update setuptools + run: | + python3 -m pip install -U setuptools - name: Build source distribution run: | python3 ./setup.py sdist diff --git a/.github/workflows/test_tox.yml b/.github/workflows/test_tox.yml index 52a2b8dc..78fbdb7e 100644 --- a/.github/workflows/test_tox.yml +++ b/.github/workflows/test_tox.yml @@ -15,15 +15,17 @@ jobs: matrix: include: - python-version: '3.7' - toxenv: 'py37' + toxenv: 'py37,wheel' - python-version: '3.8' - toxenv: 'py38' + toxenv: 'py38,wheel' - python-version: '3.9' - toxenv: 'py39' + toxenv: 'py39,wheel' - python-version: '3.10' - toxenv: 'py310' + toxenv: 'py310,wheel' - python-version: '3.11' - toxenv: 'py311' + toxenv: 'py311,wheel' + - python-version: '3.12' + toxenv: 'py312,wheel' container: image: ubuntu:22.04 steps: diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..9787c3bd --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt index a369c876..d39f42ba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -pip >= 7.0.0 PyYAML >= 3.10 cffi >= 1.9.1 cryptography >= 2.0.2 diff --git a/setup.cfg b/setup.cfg index e34dd477..7d4fb92e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,39 @@ [metadata] -license_files = LICENSE +name = dfvfs +version = 20230506 +description = Digital Forensics Virtual File System (dfVFS). +long_description = dfVFS, or Digital Forensics Virtual File System, provides read-only access to file-system objects from various storage media types and file formats. The goal of dfVFS is to provide a generic interface for accessing file-system objects, for which it uses several back-ends that provide the actual implementation of the various storage media types, volume systems and file systems. +url = https://github.com/log2timeline/dfvfs +maintainer = Log2Timeline maintainers +maintainer_email = log2timeline-maintainers@googlegroups.com +license = Apache License, Version 2.0 +license_files = + ACKNOWLEDGEMENTS + AUTHORS + LICENSE + README +classifiers = + Development Status :: 3 - Alpha + Programming Language :: Python + +[options] +install_requires = file:requirements.txt +package_dir = + dfvfs = dfvfs +packages = find: +python_requires = >=3.7 + +[options.package_data] +dfwinreg = + *.yaml + +[options.packages.find] +exclude = + docs + tests + tests.* + utils +where = . [sdist] template = MANIFEST.in @@ -12,43 +46,44 @@ manifest = MANIFEST.test_data [bdist_rpm] release = 1 packager = Log2Timeline maintainers -doc_files = ACKNOWLEDGEMENTS - AUTHORS - LICENSE - README +doc_files = + ACKNOWLEDGEMENTS + AUTHORS + LICENSE + README build_requires = python3-setuptools -requires = libbde-python3 >= 20220121 - libewf-python3 >= 20131210 - libfsapfs-python3 >= 20220709 - libfsext-python3 >= 20220829 - libfsfat-python3 >= 20220925 - libfshfs-python3 >= 20220831 - libfsntfs-python3 >= 20211229 - libfsxfs-python3 >= 20220829 - libfvde-python3 >= 20220121 - libfwnt-python3 >= 20210717 - libluksde-python3 >= 20220121 - libmodi-python3 >= 20210405 - libphdi-python3 >= 20220228 - libqcow-python3 >= 20201213 - libsigscan-python3 >= 20191221 - libsmdev-python3 >= 20140529 - libsmraw-python3 >= 20140612 - libvhdi-python3 >= 20201014 - libvmdk-python3 >= 20140421 - libvsapm-python3 >= 20230506 - libvsgpt-python3 >= 20211115 - libvshadow-python3 >= 20160109 - libvslvm-python3 >= 20160109 - python3-cffi >= 1.9.1 - python3-cryptography >= 2.0.2 - python3-dfdatetime >= 20221112 - python3-dtfabric >= 20220219 - python3-idna >= 2.5 - python3-pytsk3 >= 20210419 - python3-pyxattr >= 0.7.2 - python3-pyyaml >= 3.10 +requires = + libbde-python3 >= 20220121 + libewf-python3 >= 20131210 + libfsapfs-python3 >= 20220709 + libfsext-python3 >= 20220829 + libfsfat-python3 >= 20220925 + libfshfs-python3 >= 20220831 + libfsntfs-python3 >= 20211229 + libfsxfs-python3 >= 20220829 + libfvde-python3 >= 20220121 + libfwnt-python3 >= 20210717 + libluksde-python3 >= 20220121 + libmodi-python3 >= 20210405 + libphdi-python3 >= 20220228 + libqcow-python3 >= 20201213 + libsigscan-python3 >= 20191221 + libsmdev-python3 >= 20140529 + libsmraw-python3 >= 20140612 + libvhdi-python3 >= 20201014 + libvmdk-python3 >= 20140421 + libvsapm-python3 >= 20230506 + libvsgpt-python3 >= 20211115 + libvshadow-python3 >= 20160109 + libvslvm-python3 >= 20160109 + python3-cffi >= 1.9.1 + python3-cryptography >= 2.0.2 + python3-dfdatetime >= 20221112 + python3-dtfabric >= 20220219 + python3-idna >= 2.5 + python3-pytsk3 >= 20210419 + python3-pyxattr >= 0.7.2 + python3-pyyaml >= 3.10 [bdist_wheel] universal = 1 - diff --git a/setup.py b/setup.py index ea85c49b..888841c5 100755 --- a/setup.py +++ b/setup.py @@ -2,211 +2,7 @@ # -*- coding: utf-8 -*- """Installation and deployment script.""" -import os -import pkg_resources -import sys +from setuptools import setup -try: - from setuptools import find_packages, setup -except ImportError: - from distutils.core import find_packages, setup -try: - from distutils.command.bdist_rpm import bdist_rpm -except ImportError: - bdist_rpm = None - -try: - from setuptools.commands.sdist import sdist -except ImportError: - from distutils.command.sdist import sdist - -version_tuple = (sys.version_info[0], sys.version_info[1]) -if version_tuple < (3, 7): - print(f'Unsupported Python version: {sys.version:s}, version 3.7 or higher ' - f'required.') - sys.exit(1) - -# Change PYTHONPATH to include dfvfs so that we can get the version. -sys.path.insert(0, '.') - -import dfvfs # pylint: disable=wrong-import-position - - -if not bdist_rpm: - BdistRPMCommand = None -else: - class BdistRPMCommand(bdist_rpm): - """Custom handler for the bdist_rpm command.""" - - # pylint: disable=invalid-name - def _make_spec_file(self): - """Generates the text of an RPM spec file. - - Returns: - list[str]: lines of the RPM spec file. - """ - # Note that bdist_rpm can be an old style class. - if issubclass(BdistRPMCommand, object): - spec_file = super(BdistRPMCommand, self)._make_spec_file() - else: - spec_file = bdist_rpm._make_spec_file(self) - - python_package = 'python3' - - description = [] - requires = '' - summary = '' - in_description = False - - python_spec_file = [] - for line in iter(spec_file): - if line.startswith('Summary: '): - summary = line[9:] - - elif line.startswith('BuildRequires: '): - line = (f'BuildRequires: {python_package:s}-setuptools, ' - f'{python_package:s}-devel') - - elif line.startswith('Requires: '): - requires = line[10:] - continue - - elif line.startswith('%description'): - in_description = True - - elif line.startswith('python setup.py build'): - if python_package == 'python3': - line = '%py3_build' - else: - line = '%py2_build' - - elif line.startswith('python setup.py install'): - if python_package == 'python3': - line = '%py3_install' - else: - line = '%py2_install' - - elif line.startswith('%files'): - lines = [ - f'%files -n {python_package:s}-%{{name}}', - '%defattr(644,root,root,755)', - '%license LICENSE', - '%doc ACKNOWLEDGEMENTS AUTHORS README'] - - lines.extend([ - '%{python3_sitelib}/dfvfs/*.py', - '%{python3_sitelib}/dfvfs/*/*.py', - '%{python3_sitelib}/dfvfs/*/*.yaml', - '%{python3_sitelib}/dfvfs*.egg-info/*', - '', - '%exclude %{_prefix}/share/doc/*', - '%exclude %{python3_sitelib}/dfvfs/__pycache__/*', - '%exclude %{python3_sitelib}/dfvfs/*/__pycache__/*']) - - python_spec_file.extend(lines) - break - - elif line.startswith('%prep'): - in_description = False - - python_spec_file.append(f'%package -n {python_package:s}-%{{name}}') - python_summary = f'Python 3 module of {summary:s}' - - if requires: - python_spec_file.append(f'Requires: {requires:s}') - - python_spec_file.extend([ - f'Summary: {python_summary:s}', - '', - f'%description -n {python_package:s}-%{{name}}']) - - python_spec_file.extend(description) - - elif in_description: - # Ignore leading white lines in the description. - if not description and not line: - continue - - description.append(line) - - python_spec_file.append(line) - - return python_spec_file - - -def parse_requirements_from_file(path): - """Parses requirements from a requirements file. - - Args: - path (str): path to the requirements file. - - Returns: - list[str]: name and optional version information of the required packages. - """ - requirements = [] - if os.path.isfile(path): - with open(path, 'r') as file_object: - file_contents = file_object.read() - - for requirement in pkg_resources.parse_requirements(file_contents): - try: - name = str(requirement.req) - except AttributeError: - name = str(requirement) - - if not name.startswith('pip '): - requirements.append(name) - - return requirements - - -dfvfs_description = ( - 'Digital Forensics Virtual File System (dfVFS).') - -dfvfs_long_description = ( - 'dfVFS, or Digital Forensics Virtual File System, provides read-only ' - 'access to file-system objects from various storage media types and file ' - 'formats. The goal of dfVFS is to provide a generic interface for ' - 'accessing file-system objects, for which it uses several back-ends that ' - 'provide the actual implementation of the various storage media types, ' - 'volume systems and file systems.') - -command_classes = {'sdist_test_data': sdist} -if BdistRPMCommand: - command_classes['bdist_rpm'] = BdistRPMCommand - -setup( - name='dfvfs', - version=dfvfs.__version__, - description=dfvfs_description, - long_description=dfvfs_long_description, - long_description_content_type='text/plain', - license='Apache License, Version 2.0', - url='https://github.com/log2timeline/dfvfs', - maintainer='Log2Timeline maintainers', - maintainer_email='log2timeline-maintainers@googlegroups.com', - cmdclass=command_classes, - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Environment :: Console', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - ], - packages=find_packages('.', exclude=[ - 'docs', 'tests', 'tests.*', 'utils']), - package_dir={ - 'dfvfs': 'dfvfs' - }, - include_package_data=True, - package_data={ - 'dfvfs.lib': ['*.yaml'] - }, - zip_safe=False, - data_files=[ - ('share/doc/dfvfs', [ - 'ACKNOWLEDGEMENTS', 'AUTHORS', 'LICENSE', 'README']), - ], - install_requires=parse_requirements_from_file('requirements.txt'), - tests_require=parse_requirements_from_file('test_requirements.txt'), -) +setup() diff --git a/tox.ini b/tox.ini index 61ad0e13..1839f5b4 100644 --- a/tox.ini +++ b/tox.ini @@ -1,49 +1,54 @@ [tox] -envlist = py3{7,8,9,10,11},coverage,docs,lint +envlist = py3{7,8,9,10,11,12},coverage,docs,lint,wheel [testenv] allowlist_externals = ./run_tests.py pip_pre = True passenv = - CFLAGS - CPPFLAGS - LDFLAGS + CFLAGS + CPPFLAGS + LDFLAGS setenv = - PYTHONPATH = {toxinidir} + PYTHONPATH = {toxinidir} deps = - -rrequirements.txt - -rtest_requirements.txt - coverage: coverage + -rrequirements.txt + -rtest_requirements.txt + coverage: coverage + wheel: + build + setuptools >= 65 + wheel commands = - py3{7,8,9,10,11}: ./run_tests.py - coverage: coverage erase - coverage: coverage run --source=dfvfs --omit="*_test*,*__init__*,*test_lib*" run_tests.py - coverage: coverage xml + py3{7,8,9,10,11,12}: ./run_tests.py + coverage: coverage erase + coverage: coverage run --source=dfvfs --omit="*_test*,*__init__*,*test_lib*" run_tests.py + coverage: coverage xml + wheel: python -m build --no-isolation --wheel [testenv:docs] usedevelop = True deps = - -rdocs/requirements.txt + -rdocs/requirements.txt commands = - sphinx-build -b html -d build/doctrees docs dist/docs - sphinx-build -b linkcheck docs dist/docs + sphinx-build -b html -d build/doctrees docs dist/docs + sphinx-build -b linkcheck docs dist/docs [testenv:lint] skipsdist = True pip_pre = True passenv = - CFLAGS - CPPFLAGS - LDFLAGS + CFLAGS + CPPFLAGS + LDFLAGS setenv = - PYTHONPATH = {toxinidir} + PYTHONPATH = {toxinidir} deps = - -rrequirements.txt - -rtest_requirements.txt - pylint >= 2.17.0, < 2.18.0 - yamllint >= 1.26.0 + -rrequirements.txt + -rtest_requirements.txt + pylint >= 2.17.0, < 2.18.0 + yamllint >= 1.26.0 commands = - pylint --version - yamllint -v - pylint --rcfile=.pylintrc dfvfs tests - yamllint -c .yamllint.yaml dfvfs + pylint --version + yamllint -v + pylint --rcfile=.pylintrc dfvfs setup.py tests + yamllint -c .yamllint.yaml dfvfs