diff --git a/.github/workflows/test_docker.yml b/.github/workflows/test_docker.yml index fa60dbe..b365c03 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 python3-distutils python3-setuptools + apt-get install -y build-essential python3 python3-dev python3-distutils python3-pip python3-setuptools python3-wheel - 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_docs.yml b/.github/workflows/test_docs.yml index c92b96e..5e3bb58 100644 --- a/.github/workflows/test_docs.yml +++ b/.github/workflows/test_docs.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: include: - - python-version: '3.8' + - python-version: '3.11' toxenv: 'docs' container: image: ubuntu:22.04 diff --git a/.github/workflows/test_tox.yml b/.github/workflows/test_tox.yml index a7bd99b..9e02a93 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: @@ -58,8 +60,8 @@ jobs: strategy: matrix: include: - - python-version: '3.8' - toxenv: 'py38,coverage' + - python-version: '3.10' + toxenv: 'coverage' container: image: ubuntu:22.04 steps: diff --git a/.pylintrc b/.pylintrc index 446e1e6..877a22b 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,4 +1,4 @@ -# Pylint 2.17.x configuration file +# Pylint 3.0.x configuration file # # This file is generated by l2tdevtools update-dependencies.py, any dependency # related changes should be made in dependencies.ini. @@ -85,7 +85,6 @@ limit-inference-results=100 # List of plugins (as comma separated values of python module names) to load, # usually to register additional checkers. -# load-plugins= load-plugins=pylint.extensions.docparams # Pickle collected data for later comparisons. @@ -93,7 +92,7 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.11 +py-version=3.12 # Discover python modules and packages in the file system subtree. # recursive=no @@ -441,6 +440,7 @@ confidence=HIGH, # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use "--disable=all --enable=classes # --disable=W". + disable=assignment-from-none, bad-inline-option, consider-using-f-string, @@ -468,6 +468,8 @@ disable=assignment-from-none, too-many-return-statements, too-many-statements, unsubscriptable-object, + use-implicit-booleaness-not-comparison-to-string, + use-implicit-booleaness-not-comparison-to-zero, useless-object-inheritance, useless-suppression, use-symbolic-message-instead @@ -522,8 +524,9 @@ evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor # used to format the message information. See doc for all details. msg-template= -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio). You can also give a reporter class, e.g. +# Set the output format. Available formats are: text, parseable, colorized, +# json2 (improved json format), json (old json format) and msvs (visual +# studio). You can also give a reporter class, e.g. # mypackage.mymodule.MyReporterClass. #output-format= diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..c3c56c8 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,17 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +sphinx: + configuration: docs/conf.py + fail_on_warning: false + +python: + install: + - requirements: docs/requirements.txt diff --git a/appveyor.yml b/appveyor.yml index 13b76f0..f10b274 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,34 +1,53 @@ environment: matrix: - - DESCRIPTION: "Windows with 32-bit Python 3.11" + - DESCRIPTION: "Run tests on Windows with 32-bit Python 3.11" MACHINE_TYPE: "x86" APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 PYTHON: "C:\\Python311" PYTHON_VERSION: "3.11" L2TBINARIES_TRACK: "dev" - - DESCRIPTION: "Windows with 64-bit Python 3.11" + TARGET: tests + - DESCRIPTION: "Run tests on Windows with 64-bit Python 3.11" MACHINE_TYPE: "amd64" APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 PYTHON: "C:\\Python311-x64" PYTHON_VERSION: "3.11" L2TBINARIES_TRACK: "dev" - - DESCRIPTION: "Mac OS with Python 3.11" + TARGET: tests + - DESCRIPTION: "Build wheel on Windows with 32-bit Python 3.11" + MACHINE_TYPE: "amd64" + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + PYTHON: "C:\\Python311-x64" + PYTHON_VERSION: "3.11" + L2TBINARIES_TRACK: "dev" + TARGET: wheel + - DESCRIPTION: "Build wheel on Windows with 64-bit Python 3.11" + MACHINE_TYPE: "amd64" + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + PYTHON: "C:\\Python311-x64" + PYTHON_VERSION: "3.11" + L2TBINARIES_TRACK: "dev" + TARGET: wheel + - DESCRIPTION: "Run tests on Mac OS with Python 3.11" APPVEYOR_BUILD_WORKER_IMAGE: macos-monterey HOMEBREW_NO_INSTALL_CLEANUP: 1 + TARGET: tests install: -- cmd: "%PYTHON%\\python.exe -m pip install -U pip setuptools twine wheel" +- cmd: "%PYTHON%\\python.exe -m pip install -U build pip setuptools twine wheel" - ps: If ($isWindows) { .\config\appveyor\install.ps1 } - sh: config/appveyor/install.sh build_script: -- cmd: "%PYTHON%\\python.exe setup.py bdist_wheel" +- cmd: IF [%TARGET%]==[wheel] ( + "%PYTHON%\\python.exe" -m build --wheel ) test_script: -- cmd: "%PYTHON%\\python.exe run_tests.py" -- cmd: IF EXIST "tests\\end-to-end.py" ( - set PYTHONPATH=. && - "%PYTHON%\\python.exe" "tests\\end-to-end.py" --debug -c "config\\end-to-end.ini" ) +- cmd: IF [%TARGET%]==[tests] ( + "%PYTHON%\\python.exe" run_tests.py && + IF EXIST "tests\\end-to-end.py" ( + set PYTHONPATH=. && + "%PYTHON%\\python.exe" "tests\\end-to-end.py" --debug -c "config\\end-to-end.ini" ) ) - sh: config/appveyor/runtests.sh artifacts: diff --git a/config/appveyor/install.ps1 b/config/appveyor/install.ps1 index a1417cd..95eecae 100644 --- a/config/appveyor/install.ps1 +++ b/config/appveyor/install.ps1 @@ -21,7 +21,7 @@ If ($Dependencies.Length -gt 0) $env:PYTHONPATH = "..\l2tdevtools" - $Output = Invoke-Expression -Command "& '${env:PYTHON}\python.exe' ..\l2tdevtools\tools\update.py --download-directory dependencies --machine-type ${env:MACHINE_TYPE} ${env:L2TBINARIES_TRACK} ${Dependencies} 2>&1" | %{ "$_" } + $Output = Invoke-Expression -Command "& '${env:PYTHON}\python.exe' ..\l2tdevtools\tools\update.py --download-directory dependencies --machine-type ${env:MACHINE_TYPE} --track ${env:L2TBINARIES_TRACK} ${Dependencies} 2>&1" | %{ "$_" } Write-Host (${Output} | Out-String) } diff --git a/dfkinds.ini b/dfkinds.ini index 0b8efef..41302b9 100644 --- a/dfkinds.ini +++ b/dfkinds.ini @@ -1,6 +1,7 @@ [project] name: dfkinds name_description: dfKinds +status: experimental maintainer: Log2Timeline maintainers homepage_url: https://github.com/log2timeline/dfkinds description_short: Digital Forensics kinds (types and classes). diff --git a/docs/requirements.txt b/docs/requirements.txt index e872a91..bbbfa6b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,7 @@ +certifi >= 2023.11.17 docutils Markdown recommonmark -sphinx >= 4.1.0, < 5.2.0 +sphinx >= 4.1.0 sphinx-markdown-tables sphinx-rtd-theme >= 0.5.1 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..9787c3b --- /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 292767a..e69de29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +0,0 @@ -pip >= 7.0.0 diff --git a/setup.cfg b/setup.cfg index 36d6b39..8a50f35 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,15 +1,46 @@ [metadata] -license_files = LICENSE +name = dfkinds +version = 20231228 +description = Digital Forensics kinds (types and classes). +long_description = dfKinds, or Digital Forensics kinds, provides data type and class definitions to provide consistent definitions of entities (or description of things) across different tools. +long_description_content_type = text/plain +url = https://github.com/log2timeline/dfkinds +maintainer = Log2Timeline maintainers +maintainer_email = log2timeline-maintainers@googlegroups.com +license = Apache License, Version 2.0 +license_files = + ACKNOWLEDGEMENTS + AUTHORS + LICENSE + README +classifiers = + Development Status :: 2 - Pre-Alpha + Programming Language :: Python + +[options] +install_requires = file:requirements.txt +package_dir = + dfkinds = dfkinds +packages = find: +python_requires = >=3.7 + +[options.packages.find] +exclude = + docs + tests + tests.* + utils +where = . [bdist_rpm] release = 1 packager = Log2Timeline maintainers -doc_files = ACKNOWLEDGEMENTS - AUTHORS - LICENSE - README +doc_files = + ACKNOWLEDGEMENTS + AUTHORS + LICENSE + README build_requires = python3-setuptools [bdist_wheel] universal = 1 - diff --git a/setup.py b/setup.py index d853bf6..888841c 100755 --- a/setup.py +++ b/setup.py @@ -2,195 +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 - -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 dfkinds so that we can get the version. -sys.path.insert(0, '.') - -import dfkinds # 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}/dfkinds/*.py', - '%{python3_sitelib}/dfkinds*.egg-info/*', - '', - '%exclude %{_prefix}/share/doc/*', - '%exclude %{python3_sitelib}/dfkinds/__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 - - -dfkinds_description = ( - 'Digital Forensics kinds (types and classes).') - -dfkinds_long_description = ( - 'dfKinds, or Digital Forensics kinds, provides data type and class ' - 'definitions to provide consistent definitions of entities (or description' - ' of things) across different tools.') - -command_classes = {} -if BdistRPMCommand: - command_classes['bdist_rpm'] = BdistRPMCommand - -setup( - name='dfkinds', - version=dfkinds.__version__, - description=dfkinds_description, - long_description=dfkinds_long_description, - long_description_content_type='text/plain', - license='Apache License, Version 2.0', - url='https://github.com/log2timeline/dfkinds', - maintainer='Log2Timeline maintainers', - maintainer_email='log2timeline-maintainers@googlegroups.com', - cmdclass=command_classes, - classifiers=[ - '', - 'Environment :: Console', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - ], - packages=find_packages('.', exclude=[ - 'docs', 'tests', 'tests.*', 'utils']), - package_dir={ - 'dfkinds': 'dfkinds' - }, - data_files=[ - ('share/doc/dfkinds', [ - '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 d269de0..ac82501 100644 --- a/tox.ini +++ b/tox.ini @@ -1,46 +1,51 @@ [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=dfkinds --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=dfkinds --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 + -rrequirements.txt + -rtest_requirements.txt + pylint >= 2.17.0, < 2.18.0 commands = - pylint --version - pylint --rcfile=.pylintrc dfkinds tests + pylint --version + pylint --rcfile=.pylintrc dfkinds setup.py tests