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:
@@ -28,8 +28,10 @@ Added
|
|||||||
Changed
|
Changed
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
Replaced deprecated `pkg_resources` library with `importlib` & `packaging`
|
* Replaced deprecated `pkg_resources` library with `importlib` & `packaging`
|
||||||
for plugins discovery and loading.
|
for plugins discovery and loading.
|
||||||
|
* Implements pep-517 (pyproject.toml) and replaces pbr dependency
|
||||||
|
with setuptools-scm
|
||||||
|
|
||||||
Removed
|
Removed
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|||||||
73
pyproject.toml
Normal file
73
pyproject.toml
Normal 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"
|
||||||
@@ -116,7 +116,11 @@ def print_list(objs, fields, formatters=None, sortby_index=0,
|
|||||||
|
|
||||||
if print_border and print_row_border:
|
if print_border and print_row_border:
|
||||||
headers_horizontal_char = "="
|
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:
|
else:
|
||||||
headers_horizontal_char = "-"
|
headers_horizontal_char = "-"
|
||||||
pt = prettytable.PrettyTable(field_labels)
|
pt = prettytable.PrettyTable(field_labels)
|
||||||
@@ -143,7 +147,11 @@ def print_list(objs, fields, formatters=None, sortby_index=0,
|
|||||||
pt.add_row(row)
|
pt.add_row(row)
|
||||||
|
|
||||||
if not print_border or not print_header:
|
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.left_padding_width = 0
|
||||||
pt.right_padding_width = 1
|
pt.right_padding_width = 1
|
||||||
|
|
||||||
@@ -506,7 +514,7 @@ def _compose_action_description(action_fn):
|
|||||||
def _print_version():
|
def _print_version():
|
||||||
from rally.common import version
|
from rally.common import version
|
||||||
|
|
||||||
print("Rally version: %s" % version.version_string())
|
print("Rally version: %s" % version.__version__)
|
||||||
packages = version.plugins_versions()
|
packages = version.plugins_versions()
|
||||||
if packages:
|
if packages:
|
||||||
print("\nInstalled Plugins:")
|
print("\nInstalled Plugins:")
|
||||||
|
|||||||
@@ -13,20 +13,32 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# 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
|
from rally.common.plugin import discover as rally_discover
|
||||||
|
|
||||||
RALLY_VENDOR = "OpenStack Foundation"
|
RALLY_VENDOR = "OpenStack Foundation"
|
||||||
RALLY_PRODUCT = "OpenStack Rally"
|
RALLY_PRODUCT = "OpenStack Rally"
|
||||||
RALLY_PACKAGE = None # OS distro package version suffix
|
|
||||||
|
|
||||||
loaded = False
|
try:
|
||||||
version_info = pbr_version.VersionInfo("rally")
|
# 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():
|
__version_tuple__ = tuple(
|
||||||
return version_info.semantic_version().debian_string()
|
int(p) if p.isdigit() else p
|
||||||
|
for p in __version__.replace("-", ".").split(".")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def database_revision():
|
def database_revision():
|
||||||
@@ -42,3 +54,19 @@ def plugins_versions():
|
|||||||
(ep.dist.name, ep.dist.version)
|
(ep.dist.name, ep.dist.version)
|
||||||
for ep in rally_discover.iter_entry_points()
|
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__
|
||||||
|
|||||||
@@ -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
|
# Rally core dependencies
|
||||||
alembic!=1.2.0,!=1.6.3 # MIT
|
alembic!=1.2.0,!=1.6.3
|
||||||
Jinja2 # BSD
|
Jinja2 # BSD
|
||||||
jsonschema # MIT
|
jsonschema
|
||||||
markupsafe
|
markupsafe
|
||||||
oslo.config!=4.3.0,!=4.4.0 # Apache Software License
|
oslo.config!=4.3.0,!=4.4.0 # Apache Software License
|
||||||
# do not forget to remove `testresources` from test-requirements. it is a
|
# do not forget to remove `testresources` from test-requirements. it is a
|
||||||
# dependency of oslo.db for tests
|
# dependency of oslo.db for tests
|
||||||
oslo.db # Apache Software License
|
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
|
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
|
paramiko!=2.9.0,!=2.9.1 # LGPL
|
||||||
pbr!=2.1.0 # Apache Software License
|
PrettyTable!=3.4.0
|
||||||
PrettyTable!=3.4.0 # BSD
|
|
||||||
pyOpenSSL # Apache License, Version 2.0
|
pyOpenSSL # Apache License, Version 2.0
|
||||||
PyYAML # MIT
|
PyYAML # MIT
|
||||||
python-subunit # Apache-2.0 or BSD
|
python-subunit # Apache-2.0 or BSD
|
||||||
requests!=2.20.0,!=2.24.0 # Apache-2.0
|
requests!=2.20.0,!=2.24.0 # Apache-2.0
|
||||||
|
setuptools_scm
|
||||||
SQLAlchemy>=2 # MIT
|
SQLAlchemy>=2 # MIT
|
||||||
virtualenv!=16.3.0 # MIT
|
virtualenv!=16.3.0 # MIT
|
||||||
packaging!=20.5,!=20.6,!=20.7 # Apache Software License/BSD License
|
|
||||||
|
|||||||
45
setup.cfg
45
setup.cfg
@@ -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
|
|
||||||
21
setup.py
21
setup.py
@@ -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)
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
hacking>=4.0 # Apache Software License
|
hacking>=4.0 # Apache Software License
|
||||||
|
|
||||||
fixtures # Apache Software License/BSD License
|
fixtures # Apache-2.0 or BSD
|
||||||
pytest # MIT
|
pytest # MIT
|
||||||
# py.test plugin for measuring coverage.
|
# py.test plugin for measuring coverage.
|
||||||
pytest-cov # MIT
|
pytest-cov # MIT
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import importlib
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from rally.common import version
|
from rally.common import version
|
||||||
@@ -19,18 +20,55 @@ from tests.unit import test
|
|||||||
|
|
||||||
class ModuleTestCase(test.TestCase):
|
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):
|
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.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_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")
|
@mock.patch("rally.common.db.schema.schema_revision", return_value="foo")
|
||||||
def test_database_revision(self, mock_schema_revision):
|
def test_database_revision(self, mock_schema_revision):
|
||||||
|
|||||||
8
tox.ini
8
tox.ini
@@ -24,11 +24,11 @@ deps = -r{toxinidir}/requirements.txt
|
|||||||
usedevelop = True
|
usedevelop = True
|
||||||
pre_commands = find . -type f -name "*.pyc" -delete
|
pre_commands = find . -type f -name "*.pyc" -delete
|
||||||
commands =
|
commands =
|
||||||
pytest -vv \ # base command
|
pytest -vv \ # base command
|
||||||
--html={env:PYTEST_REPORT} \ # html report
|
--html={env:PYTEST_REPORT} \ # html report
|
||||||
--self-contained-html \ # embedded css
|
--self-contained-html \ # embedded css
|
||||||
--durations=10 \ # get a list of the slowest 10 tests
|
--durations=10 \ # get a list of the slowest 10 tests
|
||||||
-n auto \ # launch tests in parallel
|
-n auto \ # launch tests in parallel
|
||||||
{posargs:{env:TESTS_DIR}}
|
{posargs:{env:TESTS_DIR}}
|
||||||
distribute = false
|
distribute = false
|
||||||
basepython = python3
|
basepython = python3
|
||||||
|
|||||||
@@ -1,61 +1,59 @@
|
|||||||
alembic===1.14.0
|
alembic===1.16.4
|
||||||
attrs===24.2.0
|
attrs===25.3.0
|
||||||
bcrypt===4.0.1
|
bcrypt===4.0.1
|
||||||
certifi===2024.8.30
|
certifi===2025.7.14
|
||||||
cffi===1.17.1
|
cffi===1.17.1
|
||||||
charset-normalizer===3.4.0
|
charset-normalizer===3.4.2
|
||||||
cryptography===42.0.8
|
cryptography===43.0.3
|
||||||
debtcollector===3.0.0
|
debtcollector===3.0.0
|
||||||
distlib===0.3.9
|
distlib===0.4.0
|
||||||
filelock===3.16.1
|
filelock===3.18.0
|
||||||
greenlet===3.1.1
|
greenlet===3.2.3
|
||||||
idna===3.10
|
idna===3.10
|
||||||
importlib_metadata===8.5.0
|
|
||||||
iso8601===2.1.0
|
iso8601===2.1.0
|
||||||
Jinja2===3.1.4
|
Jinja2===3.1.6
|
||||||
jsonschema===4.19.2
|
jsonschema===4.25.0
|
||||||
jsonschema-specifications===2024.10.1
|
jsonschema-specifications===2025.4.1
|
||||||
Mako===1.3.6
|
Mako===1.3.10
|
||||||
MarkupSafe===3.0.2
|
MarkupSafe===3.0.2
|
||||||
msgpack===1.1.0
|
msgpack===1.1.1
|
||||||
netaddr===0.10.1
|
netaddr===1.3.0
|
||||||
oslo.config===9.7.0
|
oslo.config===10.0.0
|
||||||
oslo.context===5.7.0
|
oslo.context===6.0.0
|
||||||
oslo.db===17.0.0
|
oslo.db===17.3.0
|
||||||
oslo.i18n===6.5.0
|
oslo.i18n===6.5.1
|
||||||
oslo.log===6.1.2
|
oslo.log===7.2.0
|
||||||
oslo.serialization===5.6.0
|
oslo.serialization===5.7.0
|
||||||
oslo.utils===7.4.0
|
oslo.utils===9.0.0
|
||||||
packaging===24.2
|
packaging===25.0
|
||||||
paramiko===3.5.0
|
paramiko===3.5.1
|
||||||
pbr===6.1.0
|
pbr===6.1.1
|
||||||
pip===24.2
|
pip===25.1.1
|
||||||
platformdirs===4.3.6
|
platformdirs===4.3.8
|
||||||
prettytable===3.11.0
|
prettytable===3.16.0
|
||||||
psutil===6.1.0
|
psutil===7.0.0
|
||||||
pycparser===2.22
|
pycparser===2.22
|
||||||
PyNaCl===1.5.0
|
PyNaCl===1.5.0
|
||||||
pyOpenSSL===24.2.1
|
pyOpenSSL===24.2.1
|
||||||
pyparsing===3.2.0
|
pyparsing===3.2.3
|
||||||
python-dateutil===2.9.0.post0
|
python-dateutil===2.9.0.post0
|
||||||
python-subunit===1.4.4
|
python-subunit===1.4.4
|
||||||
PyYAML===6.0.2
|
PyYAML===6.0.2
|
||||||
referencing===0.35.1
|
referencing===0.36.2
|
||||||
requests===2.32.3
|
requests===2.32.4
|
||||||
rfc3986===2.0.0
|
rfc3986===2.0.0
|
||||||
rpds-py===0.21.0
|
rpds-py===0.26.0
|
||||||
setuptools===75.1.0
|
setuptools===80.9.0
|
||||||
six===1.16.0
|
setuptools-scm===8.3.1
|
||||||
SQLAlchemy===2.0.36
|
six===1.17.0
|
||||||
stevedore===5.4.0
|
SQLAlchemy===2.0.41
|
||||||
testresources===2.0.1
|
stevedore===5.4.1
|
||||||
|
testresources===2.0.2
|
||||||
testscenarios===0.5.0
|
testscenarios===0.5.0
|
||||||
testtools===2.7.2
|
testtools===2.7.2
|
||||||
typing_extensions===4.12.2
|
typing_extensions===4.14.1
|
||||||
tzdata===2024.2
|
tzdata===2025.2
|
||||||
urllib3===1.26.20
|
urllib3===1.26.20
|
||||||
virtualenv===20.27.1
|
virtualenv===20.31.2
|
||||||
wcwidth===0.2.13
|
wcwidth===0.2.13
|
||||||
wheel===0.44.0
|
wrapt===1.17.2
|
||||||
wrapt===1.16.0
|
|
||||||
zipp===3.21.0
|
|
||||||
|
|||||||
Reference in New Issue
Block a user