diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 1dcc069dfcc..69fc4d307a2 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -3,6 +3,8 @@ current_version = 10.0.0 commit = True tag = True +[bumpversion:file:pyproject.toml] + [bumpversion:file:kiwi/version.py] [bumpversion:file:doc/source/conf.py] diff --git a/.github/workflows/ci-units-types.yml b/.github/workflows/ci-units-types.yml index 00c2e6d846e..bb70be5aa93 100644 --- a/.github/workflows/ci-units-types.yml +++ b/.github/workflows/ci-units-types.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index 9138b3e985a..999eb6d3d1e 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,9 @@ var/ .installed.cfg *.egg +# Poetry +poetry.lock + # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. diff --git a/.virtualenv.dev-requirements.txt b/.virtualenv.dev-requirements.txt index 7687ec92ef6..5e9b6282509 100644 --- a/.virtualenv.dev-requirements.txt +++ b/.virtualenv.dev-requirements.txt @@ -4,8 +4,8 @@ -r .virtualenv.requirements.txt -# setuptools for pypi upload -setuptools +# poetry for building/installing/upload +poetry # virtualenv-based automation of test activities tox diff --git a/.virtualenv.requirements.txt b/.virtualenv.requirements.txt index 7362e2415a4..53440a1043e 100644 --- a/.virtualenv.requirements.txt +++ b/.virtualenv.requirements.txt @@ -3,7 +3,7 @@ # # Shell interface for docopt, the command-line interface description language -docopt +docopt-ng # Powerful and Pythonic XML processing library lxml @@ -14,9 +14,6 @@ PyYAML # TOML file parsing toml -# Python wrapper for extended filesystem attributes -xattr==0.9.3 - # Network request/response library requests @@ -24,7 +21,15 @@ requests anymarkup-core xmltodict +# provides pkg_resources +setuptools + # json support that also knows about tuples simplejson -typing_extensions; python_version < '3.8' +# TOML file parsing +toml + +# markup support +anymarkup-core +xmltodict diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 3ab1e1037aa..00000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,47 +0,0 @@ -# Manifest describing source package contents - -graft tools -graft dracut -graft helper -graft kiwi/boot -graft kiwi/utils -graft kiwi/markup -graft kiwi/archive -graft kiwi/bootloader -graft kiwi/builder -graft kiwi/container -graft kiwi/filesystem -graft kiwi/package_manager -graft kiwi/partitioner -graft kiwi/repository -graft kiwi/schema -graft kiwi/storage -graft kiwi/system -graft kiwi/volume_manager -graft kiwi/xsl -graft kiwi/schema -graft kiwi/config -graft kiwi/tasks -graft kiwi/solver -graft kiwi/iso_tools -graft kiwi/oci_tools -graft package -graft doc/source -graft test - -include doc/Makefile -include Makefile -include README.rst -include LICENSE -include tox.ini -include kiwi.yml - -recursive-include doc/build/man * - -include .bumpversion.cfg -include .coverage* - -include .virtualenv.requirements.txt -include .virtualenv.dev-requirements.txt - -global-exclude *.py[cod] __pycache__ diff --git a/Makefile b/Makefile index b2f1142374e..3add1a6f4c0 100644 --- a/Makefile +++ b/Makefile @@ -90,15 +90,8 @@ clean_git_attributes: git checkout kiwi/version.py build: clean tox - # create setup.py variant for rpm build. - # delete module versions from setup.py for building an rpm - # the dependencies to the python module rpm packages is - # managed in the spec file - sed -ie "s@>=[0-9.]*'@'@g" setup.py # build the sdist source tarball - $(python) setup.py sdist - # restore original setup.py backed up from sed - mv setup.pye setup.py + poetry build --format=sdist # provide rpm source tarball mv dist/kiwi-${version}.tar.gz dist/python-kiwi.tar.gz # update rpm changelog using reference file @@ -118,9 +111,11 @@ build: clean tox cp package/python-kiwi-rpmlintrc dist pypi: clean tox - $(python) setup.py sdist upload + poetry build --format=sdist + poetry publish --repository=pypi + clean: clean_git_attributes - $(python) setup.py clean + rm -rf dist rm -rf doc/build rm -rf doc/dist diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst index ac15074f70b..09ca063e3ca 100644 --- a/doc/source/contributing.rst +++ b/doc/source/contributing.rst @@ -69,49 +69,19 @@ environment for Python 3: {kiwi} uses tox to create a devel environment and to run tests, linters and other tasks in the tox generated environment. A tox version >= 3.3 is required for this setup process. On your - host a python version >= 3.7 is required for tox to work. + host a python version >= 3.9 is required for tox to work. .. code:: shell-session - $ tox -e devel - $ source .tox/devel/bin/activate + $ poetry install -The commands above automatically creates the application script +The command above automatically creates the application script called :command:`kiwi-ng`, which allows you to run {kiwi} from the -Python sources inside the virtual environment: +Python sources inside the virtual environment using Poetry: .. code:: shell-session - $ kiwi-ng --help - -.. warning:: - - The virtualenv's `$PATH` will not be taken into account when calling - {kiwi} via :command:`sudo`! Use the absolute path to the {kiwi} executable - to run an actual build using your local changes: - - .. code:: shell-session - - $ sudo $PWD/.tox/devel/bin/kiwi-ng system build ... - -To leave the development mode, run: - -.. code:: shell-session - - $ deactivate - -To resume your work, :command:`cd` into your local Git repository and call: - -.. code:: shell-session - - $ source .tox/devel/bin/activate - -Alternatively, you can launch single commands inside the virtualenv without -sourcing it directly: - -.. code:: shell-session - - $ tox -e devel -- kiwi-ng --version + $ poetry run kiwi-ng --help Running the Unit Tests diff --git a/package/python-kiwi-pkgbuild-template b/package/python-kiwi-pkgbuild-template index c7332050771..cb60f391f8d 100644 --- a/package/python-kiwi-pkgbuild-template +++ b/package/python-kiwi-pkgbuild-template @@ -8,7 +8,7 @@ pkgrel=0 pkgdesc="KIWI - Appliance Builder Next Generation" url="https://github.com/SUSE/kiwi/tarball/master" license=('GPL3') -makedepends=(python-setuptools gcc shadow grep) +makedepends=(make gcc python-build python-docopt python-installer python-lxml python-poetry-core python-requests python-setuptools python-simplejson python-sphinx python-sphinx_rtd_theme python-wheel python-yaml shadow grep) provides=(kiwi-ng kiwi) source=("${pkgname}.tar.gz") changelog="${pkgname}.changes" @@ -16,15 +16,21 @@ md5sums=('%%MD5SUM') build() { + export LANG=C.UTF-8 + export LC_ALL=C.UTF-8 cd kiwi-${pkgver} - python setup.py build + # Temporarily switch things back to docopt + # FIXME: Drop this hack as soon as we can... + sed -e "s/docopt-ng/docopt/" -i pyproject.toml + make -C doc man + python3 -m build --no-isolation --wheel } package_python-kiwi(){ depends=(python-docopt python-simplejson python-lxml python-requests python-setuptools python-yaml grub qemu squashfs-tools gptfdisk pacman e2fsprogs xfsprogs btrfs-progs libisoburn lvm2 mtools parted multipath-tools rsync tar shadow screen kiwi-man-pages) optdepends=('gnupg: keyring creation for APT package manager') cd kiwi-${pkgver} - python setup.py install --root="${pkgdir}/" --optimize=1 --skip-build + python3 -m installer --destdir "${pkgdir}/" dist/*.whl ln -sr "${pkgdir}/usr/bin/kiwi-ng" "${pkgdir}/usr/bin/kiwi" install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" } diff --git a/package/python-kiwi-spec-template b/package/python-kiwi-spec-template index d5ccf10e7ab..10344f9a6e6 100644 --- a/package/python-kiwi-spec-template +++ b/package/python-kiwi-spec-template @@ -19,18 +19,19 @@ # If they aren't provided by a system installed macro, define them %{!?_defaultdocdir: %global _defaultdocdir %{_datadir}/doc} + +%if 0%{?suse_version} && 0%{?suse_version} < 1600 +%global __python3 /usr/bin/python3.11 +%global python3_pkgversion 311 +%else %{!?__python3: %global __python3 /usr/bin/python3} +%{!?python3_pkgversion:%global python3_pkgversion 3} +%endif %if %{undefined python3_sitelib} %global python3_sitelib %(%{__python3} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") %endif -%if 0%{?el7} -%global python3_pkgversion 36 -%else -%{!?python3_pkgversion:%global python3_pkgversion 3} -%endif - %if 0%{?debian} || 0%{?ubuntu} %global is_deb 1 %global pygroup python @@ -57,9 +58,6 @@ Group: %{pygroup} Source: %{name}.tar.gz Source1: %{name}-rpmlintrc BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildRequires: gcc -BuildRequires: python%{python3_pkgversion}-%{develsuffix} >= 3.6 -BuildRequires: python%{python3_pkgversion}-setuptools %if 0%{?fedora} || 0%{?suse_version} BuildRequires: fdupes %endif @@ -69,6 +67,32 @@ BuildRequires: shadow %if 0%{?debian} || 0%{?ubuntu} BuildRequires: passwd %endif +# Main build requirements +BuildRequires: gcc +BuildRequires: make +BuildRequires: python%{python3_pkgversion}-%{develsuffix} >= 3.9 +BuildRequires: python%{python3_pkgversion}-build +BuildRequires: python%{python3_pkgversion}-installer +BuildRequires: python%{python3_pkgversion}-poetry-core >= 1.2.0 +BuildRequires: python%{python3_pkgversion}-wheel +# doc build requirements +BuildRequires: python%{python3_pkgversion}-docopt >= 0.6.2 +BuildRequires: python%{python3_pkgversion}-lxml +BuildRequires: python%{python3_pkgversion}-requests +BuildRequires: python%{python3_pkgversion}-setuptools +BuildRequires: python%{python3_pkgversion}-simplejson +%if 0%{?suse_version} +BuildRequires: python%{python3_pkgversion}-Sphinx +%else +BuildRequires: python%{python3_pkgversion}-sphinx +%endif +%if 0%{?debian} || 0%{?ubuntu} +BuildRequires: python%{python3_pkgversion}-sphinx-rtd-theme +BuildRequires: python%{python3_pkgversion}-yaml +%else +BuildRequires: python%{python3_pkgversion}-sphinx_rtd_theme +BuildRequires: python%{python3_pkgversion}-PyYAML +%endif %description The KIWI Image System provides an operating system image builder @@ -359,10 +383,9 @@ Obsoletes: python2-kiwi Conflicts: python2-kiwi Conflicts: kiwi-man-pages < %{version} Requires: screen -Requires: python%{python3_pkgversion} >= 3.6 +Requires: python%{python3_pkgversion} >= 3.9 %if 0%{?ubuntu} || 0%{?debian} Requires: python%{python3_pkgversion}-yaml -Requires: python%{python3_pkgversion}-typing-extensions %else Requires: python%{python3_pkgversion}-PyYAML %endif @@ -372,12 +395,6 @@ Requires: python%{python3_pkgversion}-lxml Requires: python%{python3_pkgversion}-requests Requires: python%{python3_pkgversion}-setuptools Requires: python%{python3_pkgversion}-xmltodict -%if 0%{?rhel} || 0%{?fedora} -Requires: (python%{python3_pkgversion}-typing-extensions if python%{python3_pkgversion} < 3.8) -%endif -%if 0%{?suse_version} -Requires: (python%{python3_pkgversion}-typing_extensions if python%{python3_pkgversion} < 3.8) -%endif %if ! (0%{?rhel} && 0%{?rhel} < 8) Recommends: kiwi-man-pages %endif @@ -601,29 +618,46 @@ Group: %{sysgroup} Provides manual pages to describe the kiwi commands %prep -%setup -q -n kiwi-%{version} +%autosetup -n kiwi-%{version} + +# Temporarily switch things back to docopt for everything but Fedora 41+ +# FIXME: Drop this hack as soon as we can... +%if ! (0%{?fedora} >= 41 || 0%{?rhel} >= 10) +sed -e "s/docopt-ng/docopt/" -i pyproject.toml +%endif # Drop shebang for kiwi/xml_parse.py, as we don't intend to use it # as an independent script sed -e "s|#!/usr/bin/env python||" -i kiwi/xml_parse.py +# Build documentation +make -C doc man + +# Build application wheel +%{__python3} -m build --no-isolation --wheel + %install -# Install Python 3 version -python3 setup.py install --prefix=%{_prefix} --root=%{buildroot} %{?is_deb:--install-layout=deb} +# Install application +%{__python3} -m installer --destdir %{buildroot} %{?is_deb:--no-compile-bytecode} dist/*.whl + +%if 0%{?is_deb} +# Fix where files were installed +mv %{buildroot}%{_prefix}/local/* %{buildroot}%{_prefix} +mv %{buildroot}%{_prefix}/lib/python3* %{buildroot}%{_prefix}/lib/python3 +%endif -# Install C-Tools, man-pages, completion and kiwi default configuration -make buildroot=%{buildroot}/ install +# Install man-pages, completion and kiwi default configuration +make buildroot=%{buildroot}/ python=%{__python3} install # Install dracut modules -make buildroot=%{buildroot}/ install_dracut +make buildroot=%{buildroot}/ python=%{__python3} install_dracut # Install documentation README / LICENSE -make buildroot=%{buildroot}/ docdir=%{_defaultdocdir}/ install_package_docs +make buildroot=%{buildroot}/ docdir=%{_defaultdocdir}/ python=%{__python3} install_package_docs # Create symlinks for correct binaries ln -sr %{buildroot}%{_bindir}/kiwi-ng %{buildroot}%{_bindir}/kiwi ln -sr %{buildroot}%{_bindir}/kiwi-ng %{buildroot}%{_bindir}/kiwi-ng-3 -ln -sr %{buildroot}%{_bindir}/kiwicompat %{buildroot}%{_bindir}/kiwicompat-3 %if "%{_vendor}" != "debbuild" # kiwi pxeboot directory structure to be packed in kiwi-pxeboot @@ -684,9 +718,7 @@ fi %dir %{_defaultdocdir}/python-kiwi %{_bindir}/kiwi %{_bindir}/kiwi-ng -%{_bindir}/kiwicompat %{_bindir}/kiwi-ng-3* -%{_bindir}/kiwicompat-3* %{python3_sitelib}/kiwi* %{_usr}/share/bash-completion/completions/kiwi-ng %{_defaultdocdir}/python-kiwi/LICENSE diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000000..a8fcb1c030a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,109 @@ +[tool.poetry] +name = "kiwi" +version = "10.0.0" +description = "KIWI - Appliance Builder" +license = "GPL-3.0-or-later" +readme = "README.rst" +homepage = "https://osinside.github.io/kiwi/" +documentation = "https://osinside.github.io/kiwi/" +repository = "https://github.com/OSInside/kiwi" + +authors = [ + "Marcus Schäfer ", +] +maintainers = [ + "Marcus Schäfer ", + "David Cassany Viladomat ", + "Neal Gompa ", + "Dan Čermák ", +] + +packages = [ + { include = "kiwi"}, +] + +include = [ + { path = ".bumpversion.cfg", format = "sdist" }, + { path = ".coverage*", format = "sdist" }, + { path = ".virtualenv.requirements*.txt", format = "sdist" }, + { path = "doc/source", format = "sdist" }, + { path = "doc/Makefile", format = "sdist" }, + { path = "dracut", format = "sdist" }, + { path = "helper", format = "sdist" }, + { path = "kiwi.yml", format = "sdist" }, + { path = "Makefile", format = "sdist" }, + { path = "package", format = "sdist" }, + { path = "test", format = "sdist" }, + { path = "tox.ini", format = "sdist" }, +] + +classifiers = [ + # classifier: http://pypi.python.org/pypi?%3Aaction=list_classifiers + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Operating System :: POSIX :: Linux", + "Topic :: System :: Operating System", +] + +[tool.poetry.urls] +"Bug Tracker" = "https://github.com/OSInside/kiwi/issues" + +[tool.poetry.dependencies] +python = "^3.9" +docopt-ng = ">=0.6.2" +lxml = ">=4.6.0" +requests = ">=2.25.0" +PyYAML = ">=5.4.0" +setuptools = ">=50" +simplejson = ">=3.17.0" + +# Optional dependencies for markup extra +anymarkup-core = { version = ">=0.8.0", optional = true } +xmltodict = { version = ">=0.12.0", optional = true } + +[tool.poetry.extras] +markup = [ "anymarkup-core", "xmltodict" ] + +[tool.poetry.plugins] +[tool.poetry.plugins."kiwi.tasks"] +image_info = "kiwi.tasks.image_info" +image_resize = "kiwi.tasks.image_resize" +result_bundle = "kiwi.tasks.result_bundle" +result_list = "kiwi.tasks.result_list" +system_build = "kiwi.tasks.system_build" +system_create = "kiwi.tasks.system_create" +system_prepare = "kiwi.tasks.system_prepare" +system_update = "kiwi.tasks.system_update" + +[tool.poetry.scripts] +kiwi-ng = "kiwi.kiwi:main" + +[tool.poetry.group.test] +[tool.poetry.group.test.dependencies] +# python unit testing framework +pytest = ">=6.2.0" +pytest-cov = "*" +pytest-xdist = "*" +pytest-container = "*" +# type checking +mypy = ">=0.971" +types-pkg_resources = "*" +types-requests = "*" +types-PyYAML = "*" +types-mock = "*" +types-simplejson = "*" + +[tool.poetry.group.style] +[tool.poetry.group.style.dependencies] +flake8 = ">=4.0.0" + +[tool.poetry.group.docs] +[tool.poetry.group.docs.dependencies] +sphinx = ">=5.0.0" +sphinx_rtd_theme = "*" +sphinxcontrib-spelling = "*" +pyenchant = "*" + +[build-system] +requires = ["poetry-core>=1.2.0"] +build-backend = "poetry.core.masonry.api" diff --git a/setup.py b/setup.py deleted file mode 100755 index 22882ad812c..00000000000 --- a/setup.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -from os import path -from setuptools import setup -from setuptools.command import sdist as setuptools_sdist - -import distutils -import subprocess - -from kiwi.version import __version__ - -here = path.abspath(path.dirname(__file__)) -with open(path.join(here, 'README.rst'), encoding='utf-8') as readme: - long_description = readme.read() - - -class sdist(setuptools_sdist.sdist): - """ - Custom sdist command - Host requirements: git - """ - def run(self): - """ - Run first the git commit format update $Format:%H$ - and after that the usual Python sdist - """ - # git attributes - command = ['make', 'git_attributes'] - self.announce( - 'Running make git_attributes target: %s' % str(command), - level=distutils.log.INFO - ) - self.announce( - subprocess.check_output(command).decode(), - level=distutils.log.INFO - ) - - # standard sdist process - setuptools_sdist.sdist.run(self) - - # cleanup attributes - command = ['make', 'clean_git_attributes'] - self.announce( - subprocess.check_output(command).decode(), - level=distutils.log.INFO - ) - - -config = { - 'name': 'kiwi', - 'long_description': long_description, - 'long_description_content_type': 'text/x-rst', - 'python_requires': '>=3.6', - 'description': 'KIWI - Appliance Builder (next generation)', - 'author': 'Marcus Schaefer', - 'url': 'https://osinside.github.io/kiwi', - 'download_url': - 'https://download.opensuse.org/repositories/' - 'Virtualization:/Appliances:/Builder', - 'author_email': 'ms@suse.com', - 'version': __version__, - 'license' : 'GPLv3+', - 'install_requires': [ - 'docopt>=0.6.2', - 'lxml', - 'requests', - 'PyYAML', - 'simplejson', - 'typing_extensions; python_version < "3.8"', - ], - 'packages': ['kiwi'], - 'cmdclass': { - 'sdist': sdist - }, - 'entry_points': { - 'kiwi.tasks': [ - 'image_info=kiwi.tasks.image_info', - 'image_resize=kiwi.tasks.image_resize', - 'result_bundle=kiwi.tasks.result_bundle', - 'result_list=kiwi.tasks.result_list', - 'system_build=kiwi.tasks.system_build', - 'system_create=kiwi.tasks.system_create', - 'system_prepare=kiwi.tasks.system_prepare', - 'system_update=kiwi.tasks.system_update' - ], - 'console_scripts': [ - 'kiwi-ng=kiwi.kiwi:main', - 'kiwicompat=kiwi.kiwi_compat:main' - ] - }, - 'include_package_data': True, - 'zip_safe': False, - 'classifiers': [ - # classifier: http://pypi.python.org/pypi?%3Aaction=list_classifiers - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: ' - 'GNU General Public License v3 or later (GPLv3+)', - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Topic :: System :: Operating System', - ] -} - -setup(**config) diff --git a/tox.ini b/tox.ini index 55865535eee..27096b100e0 100644 --- a/tox.ini +++ b/tox.ini @@ -21,14 +21,12 @@ envlist = unit_py3_11, unit_py3_10, unit_py3_9, - unit_py3_8, - unit_py3_7, packagedoc [testenv] description = - {unit_py3_7,unit_py3_8,unit_py3_9,unit_py3_10,unit_py3_11,unit_py3_12}: Unit Test run with basepython set to {basepython} + {unit_py3_9,unit_py3_10,unit_py3_11,unit_py3_12}: Unit Test run with basepython set to {basepython} devel: Test KIWI allowlist_externals = bash @@ -39,6 +37,7 @@ allowlist_externals = rm mv flake8 + poetry python pytest basepython = @@ -46,8 +45,6 @@ basepython = unit_py3_11: python3.11 unit_py3_10: python3.10 unit_py3_9: python3.9 - unit_py3_8: python3.8 - unit_py3_7: python3.7 release: python3.10 check: python3 devel: python3 @@ -59,25 +56,6 @@ deps = -r.virtualenv.dev-requirements.txt -# Test run with basepython set to 3.7 -# Only static type checking is performed for 3.7 -# because the unit test code base requires python >= 3.8 -[testenv:unit_py3_7] -setenv = - PYTHONPATH={toxinidir}/test -changedir=test/unit -commands = - {[testenv:mypy]commands} - -# Test run with basepython set to 3.8 -[testenv:unit_py3_8] -setenv = - PYTHONPATH={toxinidir}/test -changedir=test/unit -commands = - {[testenv:mypy]commands} - {[testenv:unit]commands} - # Test run with basepython set to 3.9 [testenv:unit_py3_9] setenv = @@ -145,7 +123,7 @@ passenv = deps = {[testenv]deps} changedir=test/unit commands = - bash -c 'cd ../../ && ./setup.py develop' + bash -c 'cd ../../ && poetry install --all-extras' bash -c 'cd ../../ && mypy kiwi' pytest --doctest-modules --no-cov-on-fail --cov=kiwi \ --cov-report=term-missing --cov-fail-under=100 \ @@ -257,7 +235,8 @@ deps = {[testenv]deps} skip_install = True usedevelop = True commands = - python setup.py sdist + poetry build --format=sdist + poetry publish [testenv:scripts]