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

Remove support for wheel archives. #206

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Remove support for wheel archives.
gordonmessmer committed Sep 29, 2019
commit 153b186d4bc95b4060bfbac809b36d2b37b73448
28 changes: 0 additions & 28 deletions pyp2rpm/archive.py
Original file line number Diff line number Diff line change
@@ -96,10 +96,6 @@ def is_tar(self):
def is_egg(self):
return self.suffix == '.egg'

@property
def is_wheel(self):
return self.suffix == '.whl'

def open(self):
try:
if self.extractor_cls == ZipFile:
@@ -284,30 +280,6 @@ def top_directory(self):
if self.handle:
return os.path.commonprefix(self.handle.getnames()).rstrip('/')

@property
def json_wheel_metadata(self):
"""Simple getter that get content of metadata.json file in .whl archive
Returns:
metadata from metadata.json or pydist.json in json format
"""
for meta_file in ("metadata.json", "pydist.json"):
try:
return json.loads(self.get_content_of_file(meta_file))
except TypeError as err:
logger.warning(
'Could not extract metadata from {}.'
' Error: {}'.format(meta_file, err))
sys.exit(
'Unable to extract package metadata from .whl archive. '
'This might be caused by an old .whl format version. '
'You may ask the upstream to upload fresh wheels created '
'with wheel >= 0.17.0 or to upload an sdist as well to '
'workaround this problem.')

def wheel_description(self):
"""Get content of DESCRIPTION file in .whl archive"""
return self.get_content_of_file('DESCRIPTION.rst')

@property
def record(self):
"""Getter that get content of RECORD file in .whl archive
11 changes: 3 additions & 8 deletions pyp2rpm/convertor.py
Original file line number Diff line number Diff line change
@@ -253,14 +253,9 @@ def metadata_extractor(self):
raise AttributeError("local_file attribute must be set before "
"calling metadata_extractor")
if not hasattr(self, '_metadata_extractor'):
if self.local_file.endswith('.whl'):
logger.info("Getting metadata from wheel using "
"WheelMetadataExtractor.")
extractor_cls = metadata_extractors.WheelMetadataExtractor
else:
logger.info("Getting metadata from setup.py using "
"SetupPyMetadataExtractor.")
extractor_cls = metadata_extractors.SetupPyMetadataExtractor
logger.info("Getting metadata from setup.py using "
"SetupPyMetadataExtractor.")
extractor_cls = metadata_extractors.SetupPyMetadataExtractor

base_python_version = (
self.base_python_version or self.template_base_py_ver)
87 changes: 0 additions & 87 deletions pyp2rpm/metadata_extractors.py
Original file line number Diff line number Diff line change
@@ -534,90 +534,3 @@ def data_from_archive(self):
"sphinx", self.base_python_version)])

return archive_data


class WheelMetadataExtractor(LocalMetadataExtractor):
"""Class to extract metadata from wheel archive"""

@property
def json_metadata(self):
if not hasattr(self, '_json_metadata'):
self._json_metadata = self.archive.json_wheel_metadata
return self._json_metadata

def get_requires(self, requires_types):
"""Extracts requires of given types from metadata file, filter windows
specific requires.
"""
if not isinstance(requires_types, list):
requires_types = list(requires_types)
extracted_requires = []
for requires_name in requires_types:
for requires in self.json_metadata.get(requires_name, []):
if 'win' in requires.get('environment', {}):
continue
extracted_requires.extend(requires['requires'])
return extracted_requires

@property
def runtime_deps(self):
run_requires = self.get_requires(['run_requires', 'meta_requires'])
if 'setuptools' not in run_requires:
run_requires.append('setuptools')
return self.name_convert_deps_list(deps_from_pydit_json(run_requires))

@property
def build_deps(self):
build_requires = self.get_requires(['build_requires'])
if self.has_test_suite:
build_requires += self.get_requires([
'test_requires', 'run_requires'])
if 'setuptools' not in build_requires:
build_requires.append('setuptools')
return self.name_convert_deps_list(deps_from_pydit_json(
build_requires, runtime=False))

@property
def py_modules(self):
return self.archive.record.get('modules')

@property
def scripts(self):
return self.archive.record.get('scripts', [])

@property
def home_page(self):
urls = [url for url in self.json_metadata.get('extensions', {})
.get('python.details', {})
.get('project_urls', {}).values()]
if urls:
return urls[0]

@property
@process_description
def description(self):
return self.archive.wheel_description()

@property
def summary(self):
return self.json_metadata.get('summary', None)

@property
def classifiers(self):
return self.json_metadata.get('classifiers', [])

@property
def license(self):
return self.json_metadata.get('license', None)

@property
def has_test_suite(self):
return self.has_test_files or self.json_metadata.get(
'test_requires', False) is not False

@property
def doc_files(self):
return (self.json_metadata.get('extensions', {})
.get('python.details', {})
.get('document_names', {})
.values())
44 changes: 16 additions & 28 deletions pyp2rpm/package_getters.py
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@
logger = logger = logging.getLogger(__name__)


def get_url(client, name, version, wheel=False, hashed_format=False):
def get_url(client, name, version, hashed_format=False):
"""Retrieves list of package URLs using PyPI's XML-RPC. Chooses URL
of prefered archive and md5_digest.
"""
@@ -39,29 +39,21 @@ def get_url(client, name, version, wheel=False, hashed_format=False):
url = ''
md5_digest = None

if not wheel:
# Prefered archive is tar.gz
if len(release_urls):
zip_url = zip_md5 = ''
for release_url in release_urls:
if release_url['url'].endswith("tar.gz"):
url = release_url['url']
md5_digest = release_url['md5_digest']
if release_url['url'].endswith(".zip"):
zip_url = release_url['url']
zip_md5 = release_url['md5_digest']
if url == '':
url = zip_url or release_urls[0]['url']
md5_digest = zip_md5 or release_urls[0]['md5_digest']
elif release_data:
url = release_data['download_url']
else:
# Only wheel is acceptable
# Prefered archive is tar.gz
if len(release_urls):
zip_url = zip_md5 = ''
for release_url in release_urls:
if release_url['url'].endswith("none-any.whl"):
if release_url['url'].endswith("tar.gz"):
url = release_url['url']
md5_digest = release_url['md5_digest']
break
if release_url['url'].endswith(".zip"):
zip_url = release_url['url']
zip_md5 = release_url['md5_digest']
if url == '':
url = zip_url or release_urls[0]['url']
md5_digest = zip_md5 or release_urls[0]['md5_digest']
elif release_data:
url = release_data['download_url']
if not url:
raise exceptions.MissingUrlException(
"Url of source archive not found.")
@@ -149,7 +141,7 @@ def __init__(self, client, name, version=None, save_dir=None):
'found on PyPI.'.format(name, version))
self.save_dir_init(save_dir)

def get(self, wheel=False):
def get(self):
"""Downloads the package from PyPI.
Returns:
Full path of the downloaded file.
@@ -158,14 +150,10 @@ def get(self, wheel=False):
"""
try:
url = get_url(self.client, self.name, self.version,
wheel, hashed_format=True)[0]
hashed_format=True)[0]
except exceptions.MissingUrlException as e:
raise SystemExit(e)
if wheel:
self.temp_dir = tempfile.mkdtemp()
save_dir = self.temp_dir
else:
save_dir = self.save_dir
save_dir = self.save_dir

save_file = '{0}/{1}'.format(save_dir, url.split('/')[-1])
request.urlretrieve(url, save_file)
5 changes: 1 addition & 4 deletions tests/test_convertor.py
Original file line number Diff line number Diff line change
@@ -5,8 +5,7 @@

from pyp2rpm.convertor import Convertor
from pyp2rpm.exceptions import NoSuchPackageException
from pyp2rpm.metadata_extractors import (SetupPyMetadataExtractor,
WheelMetadataExtractor)
from pyp2rpm.metadata_extractors import SetupPyMetadataExtractor
from pyp2rpm.package_getters import PypiDownloader, LocalFileGetter
from pyp2rpm.package_data import PackageData

@@ -37,8 +36,6 @@ def test_getter_bad_data(self, sf, expected):

@pytest.mark.parametrize(('sf', 'expected'), [
('{0}plumbum-0.9.0.tar.gz'.format(td_dir), SetupPyMetadataExtractor),
('{0}setuptools-19.6-py2.py3-none-any.whl'.format(td_dir),
WheelMetadataExtractor)
])
def test_get_metadata_extractor(self, sf, expected):
c = Convertor(package=sf)
Binary file not shown.
Binary file not shown.
72 changes: 0 additions & 72 deletions tests/test_metadata_extractors.py
Original file line number Diff line number Diff line change
@@ -350,75 +350,3 @@ def test_doc_files(self, doc_files, license, other):
data = self.e[0].extract_data()
assert data.data['doc_license'] == license
assert data.data['doc_files'] == other


class TestWheelMetadataExtractor(object):
td_dir = '{0}/test_data/'.format(tests_dir)

def setup_method(self, method):
self.nc = NameConvertor('fedora')
self.e = []
for archive, name, version in [
('setuptools-19.6-py2.py3-none-any.whl',
'setuptools', '19.6.2'),
('py2exe-0.9.2.2-py33.py34-none-any.whl',
'py2exe', '0.9.2.2')]:
self.e.append(me.WheelMetadataExtractor('{0}{1}'.format(
self.td_dir, archive), name, self.nc, version, venv=False))

@pytest.mark.parametrize(('i', 'what', 'expected'), [
(0, 'runtime_deps', [['Requires', 'python-certifi', '==', '2015.11.20'],
['Requires', 'python-setuptools']]),
(0, 'build_deps', [['BuildRequires', 'python2-devel'],
['BuildRequires', 'python-pytest', '>=', '2.8'],
['BuildRequires', 'python-setuptools[ssl]'],
['BuildRequires', 'python-certifi', '==',
'2015.11.20'],
['BuildRequires', 'python-setuptools']]),

(0, 'py_modules', ['_markerlib', 'pkg_resources', 'setuptools']),
(0, 'packages', ['setuptools']),
(0, 'scripts', []),
(0, 'home_page', 'https://bitbucket.org/pypa/setuptools'),
(0, 'summary', 'Easily download, build, install, upgrade, and uninstall Python packages'),
(0, 'license', 'TODO:'),
(0, 'has_pth', False),
(0, 'has_extension', False),
(0, 'has_test_suite', True),
(0, 'doc_files', ['DESCRIPTION.rst']),
(0, 'doc_license', []),
(0, 'sphinx_dir', None),
(0, 'python_versions', ['2', '3']),
(1, 'runtime_deps', [['Requires', 'python-setuptools']]),
(1, 'build_deps', [['BuildRequires', 'python2-devel'],
['BuildRequires', 'python-setuptools']]),
(1, 'py_modules', ['py2exe']),
(1, 'packages', ['py2exe']),
(1, 'scripts', ['build_exe-script.py', 'build_exe.exe']),
(1, 'home_page', 'TODO:'),
(1, 'summary', 'Build standalone executables for Windows (python 3 version)'),
(1, 'license', 'MIT/X11'),
(1, 'has_pth', False),
(1, 'has_extension', False),
(1, 'has_test_suite', False),
(1, 'doc_files', []),
(1, 'doc_license', []),
(1, 'sphinx_dir', None),
(1, 'python_versions', ['3']),

])
def test_extract(self, i, what, expected):
data = self.e[i].extract_data()
assert getattr(data, what) == expected

@pytest.mark.parametrize(("input", "expected"), [
([], ""),
(['License :: OSI Approved :: Python Software Foundation License'],
'Python'),
(['Classifier: License :: OSI Approved :: Python Software Foundation License'],
'Python'),
(['License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',
'License :: OSI Approved :: MIT License'], 'GPLv2+ and MIT'),
])
def test_license_from_trove(self, input, expected):
assert me.license_from_trove(input) == expected
Loading