Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for converting pyproject.toml-based Python3 packages. #1982

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
4 changes: 2 additions & 2 deletions lib/fpm/package/deb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ def converted_from(origin)
# Also fix the Provides field 'perl(ModuleName) = version' to be 'perl-modulename (= version)'
self.provides = self.provides.collect(&perldepfix).collect(&method(:fix_provides))

end # if origin == FPM::Packagin::CPAN
end # if origin == FPM::Package::CPAN

if origin == FPM::Package::Deb
changelog_path = staging_path("usr/share/doc/#{name}/changelog.Debian.gz")
Expand Down Expand Up @@ -1081,7 +1081,7 @@ def add_path(path, allconfigs)
FileUtils.mkdir_p(File.dirname(dcl))
FileUtils.cp_r path, dcl
else
logger.debug("Config file aready exists in staging area.")
logger.debug("Config file already exists in staging area.")
end
end
end
Expand Down
1 change: 1 addition & 0 deletions lib/fpm/package/pyfpm_wheel/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__all__ = [ "get_metadata_wheel" ]
111 changes: 111 additions & 0 deletions lib/fpm/package/pyfpm_wheel/get_metadata_wheel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import os
import sys
import pkg_resources
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The usage of pkg_resources is DEPRECATED:
https://setuptools.pypa.io/en/latest/pkg_resources.html

Users should refrain from new usage of pkg_resources and should work to port to importlib-based solutions.

import zipfile
from pkginfo import Wheel
import traceback

import json

# If you have fixes, let me know.

class get_metadata_wheel:
wheel_path = None

def __init__(self, wheel_path):
fqn = os.path.abspath(os.path.normpath(wheel_path))
if not fqn.endswith('.whl'):
raise ValueError('Wheel file must have .whl extension!')
self.wheel_path = fqn

@staticmethod
def process_dep(dep):
deps = []
if hasattr(dep, 'marker') and dep.marker:
# PEP0508 marker present
if not dep.marker.evaluate():
return deps

if dep.specs:
for operator, version in dep.specs:
deps.append("%s %s %s" % (dep.project_name,
operator, version))
else:
deps.append(dep.project_name)

return deps

@staticmethod
def get_home_url(project_urls):
res = dict([i.strip() for i in x.split(',')] for x in project_urls)
amdei marked this conversation as resolved.
Show resolved Hide resolved
if 'Home' in res:
return res.get('Home', None)
return res.get('Homepage', None)


def __wheel_root_is_pure(self):
with zipfile.ZipFile(self.wheel_path, mode="r") as archive:
names = archive.namelist()
for name in names:
if name.endswith('.dist-info/WHEEL'):
for line in archive.read(name).split(b"\n"):
line_lower = str(line.decode()).lower().strip()
if line_lower.startswith('root-is-purelib') and line_lower.endswith('true'):
return True

return False


def run(self, output_path):

fpm_wheel = Wheel(self.wheel_path)
data = {
"name": fpm_wheel.name,
"version": fpm_wheel.version,
"description": fpm_wheel.summary,
"license": fpm_wheel.license,
}

if fpm_wheel.author:
data["author"] = "%s" % fpm_wheel.author
else:
data["author"] = "Unknown"

if fpm_wheel.author_email:
data["author"] = data["author"] + " <%s>" % fpm_wheel.author_email
else:
data["author"] = data["author"] + " <unknown@unknown.unknown>"


if fpm_wheel.home_page:
data["url"] = fpm_wheel.home_page
else:
data["url"] = self.get_home_url(fpm_wheel.project_urls)

# @todo Can anyone provide a python package, where fpm_wheel.requires_external would result in 'true'?
if self.__wheel_root_is_pure() and not fpm_wheel.requires_external:
data["architecture"] = "all"
else:
data["architecture"] = "native"

final_deps = []

try:
if fpm_wheel.requires_dist:
for dep in pkg_resources.parse_requirements(fpm_wheel.requires_dist):
final_deps.extend(self.process_dep(dep))
except Exception as e:
raise

data["dependencies"] = final_deps

with open(output_path, "w") as output:
def default_to_str(obj):
""" Fall back to using __str__ if possible """
# This checks if the class of obj defines __str__ itself,
# so we don't fall back to an inherited __str__ method.
if "__str__" in type(obj).__dict__:
return str(obj)
return json.JSONEncoder.default(json.JSONEncoder(), obj)

output.write(json.dumps(data, indent=2, sort_keys=True, default=default_to_str))
Loading