Use setuptools_scm instead of pbr and implement pep-517

This removes setup.cfg and setup.py files by replacing them by
a single pyproject.toml

Signed-off-by: Andriy Kurilin <andr.kurilin@gmail.com>
Change-Id: I220dafc2cfb0bbd92249efdf2ad713afe1e6d3d5
This commit is contained in:
Andriy Kurilin
2024-12-03 12:41:00 +01:00
parent 5e83ecf74d
commit 62eef98850
11 changed files with 219 additions and 141 deletions

View File

@@ -28,8 +28,10 @@ Added
Changed
~~~~~~~
Replaced deprecated `pkg_resources` library with `importlib` & `packaging`
for plugins discovery and loading.
* Replaced deprecated `pkg_resources` library with `importlib` & `packaging`
for plugins discovery and loading.
* Implements pep-517 (pyproject.toml) and replaces pbr dependency
with setuptools-scm
Removed
~~~~~~~

73
pyproject.toml Normal file
View File

@@ -0,0 +1,73 @@
[project]
name = "rally"
description = "Generic Testing Framework & Tool that unifies all types of testing"
authors = [
{name = "OpenStack", email = "openstack-discuss@lists.openstack.org"},
]
readme = "README.rst"
license = { text = "Apache License, Version 2.0"}
classifiers = [
"Environment :: OpenStack",
"Intended Audience :: Developers",
"Intended Audience :: Information Technology",
"License :: OSI Approved :: Apache Software License",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dynamic = ["version", "dependencies"]
requires-python = ">=3.9"
[project.urls]
Homepage = "https://rally.readthedocs.io/"
Issues = "https://bugs.launchpad.net/rally"
Source = "https://opendev.org/openstack/rally"
Github = "https://github.com/openstack/rally"
Changelog = "https://github.com/openstack/rally/blob/master/CHANGELOG.rst"
[build-system]
requires = [
"setuptools>=64",
"setuptools_scm>=8"
]
build-backend = "setuptools.build_meta"
[tool.setuptools]
include-package-data = true
[tool.setuptools.data-files]
"etc/bash_completion.d" = ["etc/rally.bash_completion"]
[tool.setuptools.dynamic]
dependencies = {file = ["requirements.txt"]}
[project.optional-dependencies]
mysql = [
"PyMySQL>=0.7.6" # MIT
]
postgres = [
"psycopg2>=2.5" # LGPL/ZPL
]
[tool.setuptools_scm]
local_scheme = "no-local-version"
[tool.setuptools.packages.find]
where = ["."]
include = ["rally*"]
exclude = ["tests"]
[project.scripts]
rally = "rally.cli.main:main"
[project.entry-points."oslo.config.opts"]
rally = "rally.common.opts:list_opts"
[project.entry-points."oslo.config.opts.defaults"]
rally = "rally.common.opts:update_opt_defaults"

View File

@@ -116,7 +116,11 @@ def print_list(objs, fields, formatters=None, sortby_index=0,
if print_border and print_row_border:
headers_horizontal_char = "="
kwargs["hrules"] = prettytable.ALL
try:
kwargs["hrules"] = prettytable.HRuleStyle.ALL
except AttributeError: # pragma: no cover
# old prettytable
kwargs["hrules"] = prettytable.ALL
else:
headers_horizontal_char = "-"
pt = prettytable.PrettyTable(field_labels)
@@ -143,7 +147,11 @@ def print_list(objs, fields, formatters=None, sortby_index=0,
pt.add_row(row)
if not print_border or not print_header:
pt.set_style(prettytable.PLAIN_COLUMNS)
try:
pt.set_style(prettytable.TableStyle.PLAIN_COLUMNS)
except AttributeError: # pragma: no cover
# old prettytable
pt.set_style(prettytable.PLAIN_COLUMNS)
pt.left_padding_width = 0
pt.right_padding_width = 1
@@ -506,7 +514,7 @@ def _compose_action_description(action_fn):
def _print_version():
from rally.common import version
print("Rally version: %s" % version.version_string())
print("Rally version: %s" % version.__version__)
packages = version.plugins_versions()
if packages:
print("\nInstalled Plugins:")

View File

@@ -13,20 +13,32 @@
# License for the specific language governing permissions and limitations
# under the License.
from pbr import version as pbr_version
from importlib.metadata import version as _version
from rally.common.plugin import discover as rally_discover
RALLY_VENDOR = "OpenStack Foundation"
RALLY_PRODUCT = "OpenStack Rally"
RALLY_PACKAGE = None # OS distro package version suffix
loaded = False
version_info = pbr_version.VersionInfo("rally")
try:
# Try to get version from installed package metadata
__version__ = _version("rally")
except Exception:
# Fallback to setuptools_scm for development installs
try:
from setuptools_scm import get_version
__version__ = get_version()
except Exception:
# Final fallback - this should rarely happen
__version__ = "0.0.0"
def version_string():
return version_info.semantic_version().debian_string()
__version_tuple__ = tuple(
int(p) if p.isdigit() else p
for p in __version__.replace("-", ".").split(".")
)
def database_revision():
@@ -42,3 +54,19 @@ def plugins_versions():
(ep.dist.name, ep.dist.version)
for ep in rally_discover.iter_entry_points()
)
# backward compatibility
class version_info:
@classmethod
def semantic_version(cls):
return cls
@classmethod
def version_tuple(cls):
return __version_tuple__
def version_string():
return __version__

View File

@@ -1,24 +1,21 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
# Rally core dependencies
alembic!=1.2.0,!=1.6.3 # MIT
alembic!=1.2.0,!=1.6.3
Jinja2 # BSD
jsonschema # MIT
jsonschema
markupsafe
oslo.config!=4.3.0,!=4.4.0 # Apache Software License
# do not forget to remove `testresources` from test-requirements. it is a
# dependency of oslo.db for tests
oslo.db # Apache Software License
oslo.log!=3.44.2,!=4.1.2,!=4.2.0,!=5.0.1,!=5.0.2,!=5.1.0 # Apache Software License
packaging!=20.5,!=20.6,!=20.7 # Apache Software License/BSD License
paramiko!=2.9.0,!=2.9.1 # LGPL
pbr!=2.1.0 # Apache Software License
PrettyTable!=3.4.0 # BSD
PrettyTable!=3.4.0
pyOpenSSL # Apache License, Version 2.0
PyYAML # MIT
python-subunit # Apache-2.0 or BSD
requests!=2.20.0,!=2.24.0 # Apache-2.0
setuptools_scm
SQLAlchemy>=2 # MIT
virtualenv!=16.3.0 # MIT
packaging!=20.5,!=20.6,!=20.7 # Apache Software License/BSD License

View File

@@ -1,45 +0,0 @@
[metadata]
name = rally
summary = Generic Testing Framework & Tool that unifies all types of testing.
description_file =
README.rst
author = OpenStack
author_email = openstack-discuss@lists.openstack.org
home_page = https://rally.readthedocs.io/
license = Apache License, Version 2.0
requires_python = >=3.9
classifier =
Environment :: OpenStack
Intended Audience :: Developers
Intended Audience :: Information Technology
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
[files]
packages =
rally
data_files =
etc/bash_completion.d =
etc/rally.bash_completion
[entry_points]
console_scripts =
rally = rally.cli.main:main
oslo.config.opts =
rally = rally.common.opts:list_opts
oslo.config.opts.defaults =
rally = rally.common.opts:update_opt_defaults
[extras]
mysql =
PyMySQL>=0.7.6 # MIT
postgres =
psycopg2>=2.5 # LGPL/ZPL

View File

@@ -1,21 +0,0 @@
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import setuptools
setuptools.setup(
setup_requires=['pbr>=1.8'],
pbr=True)

View File

@@ -4,7 +4,7 @@
hacking>=4.0 # Apache Software License
fixtures # Apache Software License/BSD License
fixtures # Apache-2.0 or BSD
pytest # MIT
# py.test plugin for measuring coverage.
pytest-cov # MIT

View File

@@ -11,6 +11,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import importlib
from unittest import mock
from rally.common import version
@@ -19,18 +20,55 @@ from tests.unit import test
class ModuleTestCase(test.TestCase):
VERSION_REGEX = r"^\d+\.\d+\.\d+(~dev\d+)?$"
VERSION_REGEX = r"^\d+\.\d+\.\d+(\.dev\d+)?$"
def test_version_info(self):
version_str = version.version_info.semantic_version().debian_string()
version_str = version.version_string()
self.assertRegex(version_str, self.VERSION_REGEX)
self.assertNotEqual("0.0.0", version_str)
self.assertEqual(
version.__version_tuple__,
version.version_info.semantic_version().version_tuple()
)
@mock.patch("setuptools_scm.get_version")
@mock.patch("importlib.metadata.version")
def test_version_string(self, mock_version, mock_get_version):
self.addCleanup(lambda: importlib.reload(version))
mock_version.return_value = "foo_version"
mock_get_version.return_value = "bar_version"
# reload module, so it can rediscover version
importlib.reload(version)
# ensure that we reload version after the test
self.addCleanup(lambda: importlib.reload(version))
@mock.patch("rally.common.version.version_info")
def test_version_string(self, mock_version_info):
mock_sv = mock.Mock()
mock_sv.debian_string.return_value = "foo_version"
mock_version_info.semantic_version.return_value = mock_sv
self.assertEqual("foo_version", version.version_string())
self.assertEqual("foo_version", version.__version__)
mock_version.assert_called_once_with("rally")
self.assertFalse(mock_get_version.called)
# check fallback
mock_version.reset_mock()
mock_version.side_effect = Exception("oops")
importlib.reload(version)
self.assertEqual("bar_version", version.__version__)
mock_version.assert_called_once_with("rally")
mock_get_version.assert_called_once_with()
# check fallback 2
mock_version.reset_mock()
mock_get_version.reset_mock()
mock_get_version.side_effect = Exception("oops2")
importlib.reload(version)
self.assertEqual("0.0.0", version.__version__)
mock_version.assert_called_once_with("rally")
mock_get_version.assert_called_once_with()
@mock.patch("rally.common.db.schema.schema_revision", return_value="foo")
def test_database_revision(self, mock_schema_revision):

View File

@@ -24,11 +24,11 @@ deps = -r{toxinidir}/requirements.txt
usedevelop = True
pre_commands = find . -type f -name "*.pyc" -delete
commands =
pytest -vv \ # base command
pytest -vv \ # base command
--html={env:PYTEST_REPORT} \ # html report
--self-contained-html \ # embedded css
--durations=10 \ # get a list of the slowest 10 tests
-n auto \ # launch tests in parallel
--self-contained-html \ # embedded css
--durations=10 \ # get a list of the slowest 10 tests
-n auto \ # launch tests in parallel
{posargs:{env:TESTS_DIR}}
distribute = false
basepython = python3

View File

@@ -1,61 +1,59 @@
alembic===1.14.0
attrs===24.2.0
alembic===1.16.4
attrs===25.3.0
bcrypt===4.0.1
certifi===2024.8.30
certifi===2025.7.14
cffi===1.17.1
charset-normalizer===3.4.0
cryptography===42.0.8
charset-normalizer===3.4.2
cryptography===43.0.3
debtcollector===3.0.0
distlib===0.3.9
filelock===3.16.1
greenlet===3.1.1
distlib===0.4.0
filelock===3.18.0
greenlet===3.2.3
idna===3.10
importlib_metadata===8.5.0
iso8601===2.1.0
Jinja2===3.1.4
jsonschema===4.19.2
jsonschema-specifications===2024.10.1
Mako===1.3.6
Jinja2===3.1.6
jsonschema===4.25.0
jsonschema-specifications===2025.4.1
Mako===1.3.10
MarkupSafe===3.0.2
msgpack===1.1.0
netaddr===0.10.1
oslo.config===9.7.0
oslo.context===5.7.0
oslo.db===17.0.0
oslo.i18n===6.5.0
oslo.log===6.1.2
oslo.serialization===5.6.0
oslo.utils===7.4.0
packaging===24.2
paramiko===3.5.0
pbr===6.1.0
pip===24.2
platformdirs===4.3.6
prettytable===3.11.0
psutil===6.1.0
msgpack===1.1.1
netaddr===1.3.0
oslo.config===10.0.0
oslo.context===6.0.0
oslo.db===17.3.0
oslo.i18n===6.5.1
oslo.log===7.2.0
oslo.serialization===5.7.0
oslo.utils===9.0.0
packaging===25.0
paramiko===3.5.1
pbr===6.1.1
pip===25.1.1
platformdirs===4.3.8
prettytable===3.16.0
psutil===7.0.0
pycparser===2.22
PyNaCl===1.5.0
pyOpenSSL===24.2.1
pyparsing===3.2.0
pyparsing===3.2.3
python-dateutil===2.9.0.post0
python-subunit===1.4.4
PyYAML===6.0.2
referencing===0.35.1
requests===2.32.3
referencing===0.36.2
requests===2.32.4
rfc3986===2.0.0
rpds-py===0.21.0
setuptools===75.1.0
six===1.16.0
SQLAlchemy===2.0.36
stevedore===5.4.0
testresources===2.0.1
rpds-py===0.26.0
setuptools===80.9.0
setuptools-scm===8.3.1
six===1.17.0
SQLAlchemy===2.0.41
stevedore===5.4.1
testresources===2.0.2
testscenarios===0.5.0
testtools===2.7.2
typing_extensions===4.12.2
tzdata===2024.2
typing_extensions===4.14.1
tzdata===2025.2
urllib3===1.26.20
virtualenv===20.27.1
virtualenv===20.31.2
wcwidth===0.2.13
wheel===0.44.0
wrapt===1.16.0
zipp===3.21.0
wrapt===1.17.2