Skip to content

Commit

Permalink
Migrate from setup.py to pyproject.toml.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kami committed Aug 2, 2023
1 parent e26f012 commit 5f19fd8
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 273 deletions.
9 changes: 7 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
global-exclude *.py[cod]
global-exclude .pytest_cache
include LICENSE
include NOTICE
include example_*.py
Expand All @@ -8,8 +10,6 @@ include pyproject.toml
include requirements-tests.txt
include requirements-lint.txt
include libcloud/data/pricing.json
prune libcloud/test/secrets.py
prune requirements-rtd.txt
include demos/*
include scripts/check_file_names.sh
include libcloud/test/*.py
Expand All @@ -26,3 +26,8 @@ include libcloud/test/compute/fixtures/*/*/*
include libcloud/test/storage/fixtures/*/*
include libcloud/test/loadbalancer/fixtures/*/*
include libcloud/test/dns/fixtures/*/*
recursive-exclude libcloud/test secrets.py
prune libcloud/test/secrets.py
prune requirements-rtd.txt
prune dist
prune build
87 changes: 85 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,93 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

[build-system]
requires = ["setuptools~=66.1", "wheel~=0.37.1"]
requires = [
"setuptools~=66.1",
"wheel~=0.37.1"
]
build-backend = "setuptools.build_meta"

[project]
name = "apache-libcloud"
description = "A standard Python library that abstracts away differences among multiple cloud provider APIs. For more information and documentation, please see https://libcloud.apache.org"
authors = [
{name = "Apache Software Foundation", email = "dev@libcloud.apache.org"},
]
keywords = [
"cloud",
"libcloud",
"apache",
"aws",
"ec2",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Software Development :: Libraries :: Python Modules",
]
requires-python = ">=3.7"
dependencies = [
"requests>=2.26.0",
]
license = {text = "Apache License (2.0)"}
dynamic = ["version", "readme"]

[project.urls]
homepage = "https://libcloud.apache.org"
documentation = "https://libcloud.readthedocs.io"
source = "https://github.com/apache/libcloud"
issues = "https://github.com/apache/libcloud/issues"
changelog = "https://github.com/apache/libcloud/blob/trunk/CHANGES.rst"


[project.optional-dependencies]
test = [
"pytest",
"requests_mock",
]

[tool.setuptools.packages.find]
where = ["./"]
include = ["libcloud"]

[tool.setuptools]
exclude-package-data = { "*" = ["secrets.py"], "libcloud.test" = ["secrets.py"] }

[tool.setuptools.dynamic]
version = {attr = "libcloud.__version__"}
readme = {file = ["README.rst"]}


[tool.black]
line_length = 100
target_version = ['py37', 'py38', 'py39', 'py310']
target_version = ['py37', 'py38', 'py39', 'py310', 'py311']
include = '\.pyi?$'
extended_exclude = '''
(
Expand Down
270 changes: 1 addition & 269 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,272 +21,4 @@
import setuptools
from setuptools import setup

# NOTE: Those functions are intentionally moved in-line to prevent setup.py dependening on any
# Libcloud code which depends on libraries such as typing, enum, requests, etc.
# START: Taken From Twisted Python which licensed under MIT license
# https://github.com/powdahound/twisted/blob/master/twisted/python/dist.py
# https://github.com/powdahound/twisted/blob/master/LICENSE

# Names that are excluded from globbing results:
EXCLUDE_NAMES = ["{arch}", "CVS", ".cvsignore", "_darcs", "RCS", "SCCS", ".svn"]
EXCLUDE_PATTERNS = ["*.py[cdo]", "*.s[ol]", ".#*", "*~", "*.py"]


def _filter_names(names):
"""
Given a list of file names, return those names that should be copied.
"""
names = [n for n in names if n not in EXCLUDE_NAMES]
# This is needed when building a distro from a working
# copy (likely a checkout) rather than a pristine export:
for pattern in EXCLUDE_PATTERNS:
names = [n for n in names if not fnmatch.fnmatch(n, pattern) and not n.endswith(".py")]
return names


def relative_to(base, relativee):
"""
Gets 'relativee' relative to 'basepath'.
i.e.,
>>> relative_to('/home/', '/home/radix/')
'radix'
>>> relative_to('.', '/home/radix/Projects/Twisted')
'Projects/Twisted'
The 'relativee' must be a child of 'basepath'.
"""
basepath = os.path.abspath(base)
relativee = os.path.abspath(relativee)
if relativee.startswith(basepath):
relative = relativee[len(basepath) :]
if relative.startswith(os.sep):
relative = relative[1:]
return os.path.join(base, relative)
raise ValueError("%s is not a subpath of %s" % (relativee, basepath))


def get_packages(dname, pkgname=None, results=None, ignore=None, parent=None):
"""
Get all packages which are under dname. This is necessary for
Python 2.2's distutils. Pretty similar arguments to getDataFiles,
including 'parent'.
"""
parent = parent or ""
prefix = []
if parent:
prefix = [parent]
bname = os.path.basename(dname)
ignore = ignore or []
if bname in ignore:
return []
if results is None:
results = []
if pkgname is None:
pkgname = []
subfiles = os.listdir(dname)
abssubfiles = [os.path.join(dname, x) for x in subfiles]

if "__init__.py" in subfiles:
results.append(prefix + pkgname + [bname])
for subdir in filter(os.path.isdir, abssubfiles):
get_packages(
subdir,
pkgname=pkgname + [bname],
results=results,
ignore=ignore,
parent=parent,
)
res = [".".join(result) for result in results]
return res


def get_data_files(dname, ignore=None, parent=None):
"""
Get all the data files that should be included in this distutils Project.
'dname' should be the path to the package that you're distributing.
'ignore' is a list of sub-packages to ignore. This facilitates
disparate package hierarchies. That's a fancy way of saying that
the 'twisted' package doesn't want to include the 'twisted.conch'
package, so it will pass ['conch'] as the value.
'parent' is necessary if you're distributing a subpackage like
twisted.conch. 'dname' should point to 'twisted/conch' and 'parent'
should point to 'twisted'. This ensures that your data_files are
generated correctly, only using relative paths for the first element
of the tuple ('twisted/conch/*').
The default 'parent' is the current working directory.
"""
parent = parent or "."
ignore = ignore or []
result = []
for directory, subdirectories, filenames in os.walk(dname):
resultfiles = []
for exname in EXCLUDE_NAMES:
if exname in subdirectories:
subdirectories.remove(exname)
for ig in ignore:
if ig in subdirectories:
subdirectories.remove(ig)
for filename in _filter_names(filenames):
resultfiles.append(filename)
if resultfiles:
for filename in resultfiles:
file_path = os.path.join(directory, filename)
if parent:
file_path = file_path.replace(parent + os.sep, "")
result.append(file_path)

return result


# END: Taken from Twisted


# Different versions of python have different requirements. We can't use
# libcloud.utils.py3 here because it relies on backports dependency being
# installed / available
PY_pre_37 = sys.version_info < (3, 7, 0)

HTML_VIEWSOURCE_BASE = "https://svn.apache.org/viewvc/libcloud/trunk"
PROJECT_BASE_DIR = "https://libcloud.apache.org"
TEST_PATHS = [
"libcloud/test",
"libcloud/test/common",
"libcloud/test/compute",
"libcloud/test/storage",
"libcloud/test/loadbalancer",
"libcloud/test/dns",
"libcloud/test/container",
"libcloud/test/backup",
]
DOC_TEST_MODULES = [
"libcloud.compute.drivers.dummy",
"libcloud.storage.drivers.dummy",
"libcloud.dns.drivers.dummy",
"libcloud.container.drivers.dummy",
"libcloud.backup.drivers.dummy",
]

SUPPORTED_VERSIONS = ["PyPy 3.7+", "Python 3.7+"]

# NOTE: python_version syntax is only supported when build system has
# setuptools >= 36.2
# For installation, minimum required pip version is 1.4
# Reference: https://hynek.me/articles/conditional-python-dependencies/
# We rely on >= 2.26.0 to avoid issues with LGPL transitive dependency
# See https://github.com/apache/libcloud/issues/1594 for more context
INSTALL_REQUIREMENTS = []
INSTALL_REQUIREMENTS.append("requests>=2.26.0")


setuptools_version = tuple(setuptools.__version__.split(".")[0:2])
setuptools_version = tuple([int(c) for c in setuptools_version])

if setuptools_version < (36, 2):
if "bdist_wheel" in sys.argv:
# NOTE: We need to do that because we use universal wheel
msg = (
"Need to use latest version of setuptools when building wheels to ensure included "
"metadata is correct. Current version: %s" % (setuptools.__version__)
)
raise RuntimeError(msg)

TEST_REQUIREMENTS = [
"requests_mock",
"pytest",
"pytest-runner",
] + INSTALL_REQUIREMENTS

if PY_pre_37:
version = ".".join([str(x) for x in sys.version_info[:3]])
print(
"Python version %s is not supported. Supported versions are: %s. "
"Latest version which supports Python 2.7 and Python 3 < 3.5.0 is "
"Libcloud v2.8.2 and Libcloud v3.5.x for Python 3.5."
% (version, ", ".join(SUPPORTED_VERSIONS))
)
sys.exit(1)


def read_version_string():
version = None
cwd = os.path.dirname(os.path.abspath(__file__))
version_file = os.path.join(cwd, "libcloud/__init__.py")

with open(version_file) as fp:
content = fp.read()

match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", content, re.M)

if match:
version = match.group(1)
return version

raise Exception("Cannot find version in libcloud/__init__.py")


def forbid_publish():
argv = sys.argv
if "upload" in argv:
print(
"You shouldn't use upload command to upload a release to PyPi. "
"You need to manually upload files generated using release.sh "
"script.\n"
'For more information, see "Making a release section" in the '
"documentation"
)
sys.exit(1)


forbid_publish()

needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv)
pytest_runner = ["pytest-runner"] if needs_pytest else []

setup(
name="apache-libcloud",
version=read_version_string(),
description="A standard Python library that abstracts away differences"
+ " among multiple cloud provider APIs. For more information"
+ " and documentation, please see https://libcloud.apache.org",
long_description=open("README.rst").read(),
author="Apache Software Foundation",
author_email="dev@libcloud.apache.org",
install_requires=INSTALL_REQUIREMENTS,
python_requires=">=3.6, <4",
packages=get_packages("libcloud"),
package_dir={
"libcloud": "libcloud",
},
package_data={
"libcloud": get_data_files("libcloud", parent="libcloud") + ["py.typed"],
},
license="Apache License (2.0)",
url="https://libcloud.apache.org/",
setup_requires=pytest_runner,
tests_require=TEST_REQUIREMENTS,
zip_safe=False,
classifiers=[
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Topic :: Software Development :: Libraries :: Python Modules",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
],
)
setup()

0 comments on commit 5f19fd8

Please sign in to comment.