Any package built by scanpypi should be manually checked for
errors.
"""
-from __future__ import print_function
-from __future__ import absolute_import
import argparse
import json
import sys
liclookup = None
+def toml_load(f):
+ with open(f, 'rb') as fh:
+ ex = None
+
+ # Try standard library tomllib first
+ try:
+ from tomllib import load
+ return load(fh)
+ except ImportError:
+ pass
+
+ # Try regular tomli next
+ try:
+ from tomli import load
+ return load(fh)
+ except ImportError as e:
+ ex = e
+
+ # Try pip's vendored tomli
+ try:
+ from pip._vendor.tomli import load
+ try:
+ return load(fh)
+ except TypeError:
+ # Fallback to handle older version
+ try:
+ fh.seek(0)
+ w = io.TextIOWrapper(fh, encoding="utf8", newline="")
+ return load(w)
+ finally:
+ w.detach()
+ except ImportError:
+ pass
+
+ # Try regular toml last
+ try:
+ from toml import load
+ fh.seek(0)
+ w = io.TextIOWrapper(fh, encoding="utf8", newline="")
+ try:
+ return load(w)
+ finally:
+ w.detach()
+ except ImportError:
+ pass
+
+ print('This package needs tomli')
+ raise ex
+
+
def setup_decorator(func, method):
"""
Decorator for distutils.core.setup and setuptools.setup.
"""
current_dir = os.getcwd()
os.chdir(self.tmp_extract)
- sys.path.append(self.tmp_extract)
- s_file, s_path, s_desc = imp.find_module('setup', [self.tmp_extract])
- setup = imp.load_module('setup', s_file, s_path, s_desc)
- if self.metadata_name in self.setup_args:
- pass
- elif self.metadata_name.replace('_', '-') in self.setup_args:
- self.metadata_name = self.metadata_name.replace('_', '-')
- elif self.metadata_name.replace('-', '_') in self.setup_args:
- self.metadata_name = self.metadata_name.replace('-', '_')
+ sys.path.insert(0, self.tmp_extract)
+ try:
+ s_file, s_path, s_desc = imp.find_module('setup', [self.tmp_extract])
+ imp.load_module('__main__', s_file, s_path, s_desc)
+ if self.metadata_name in self.setup_args:
+ pass
+ elif self.metadata_name.replace('_', '-') in self.setup_args:
+ self.metadata_name = self.metadata_name.replace('_', '-')
+ elif self.metadata_name.replace('-', '_') in self.setup_args:
+ self.metadata_name = self.metadata_name.replace('-', '_')
+ try:
+ self.setup_metadata = self.setup_args[self.metadata_name]
+ except KeyError:
+ # This means setup was not called
+ print('ERROR: Could not determine package metadata for {pkg}.\n'
+ .format(pkg=self.real_name))
+ raise
+ finally:
+ os.chdir(current_dir)
+ sys.path.remove(self.tmp_extract)
+
+ def load_pyproject(self):
+ """
+ Loads the corresponding pyproject.toml and store its metadata
+ """
+ current_dir = os.getcwd()
+ os.chdir(self.tmp_extract)
+ sys.path.insert(0, self.tmp_extract)
try:
- self.setup_metadata = self.setup_args[self.metadata_name]
- except KeyError:
- # This means setup was not called which most likely mean that it is
- # called through the if __name__ == '__main__' directive.
- # In this case, we can only pray that it is called through a
- # function called main() in setup.py.
- setup.main() # Will raise AttributeError if not found
- self.setup_metadata = self.setup_args[self.metadata_name]
- # Here we must remove the module the hard way.
- # We must do this because of a very specific case: if a package calls
- # setup from the __main__ but does not come with a 'main()' function,
- # for some reason setup.main() will successfully call the main
- # function of a previous package...
- sys.modules.pop('setup', None)
- del setup
+ pyproject_data = toml_load('pyproject.toml')
+ try:
+ self.setup_metadata = pyproject_data.get('project', {})
+ self.metadata_name = self.setup_metadata.get('name', self.real_name)
+ build_system = pyproject_data.get('build-system', {})
+ build_backend = build_system.get('build-backend', None)
+ if build_backend and build_backend == 'flit_core.buildapi':
+ self.setup_metadata['method'] = 'flit'
+ elif build_system.get('backend-path', None):
+ self.setup_metadata['method'] = 'pep517'
+ else:
+ self.setup_metadata['method'] = 'unknown'
+ except KeyError:
+ print('ERROR: Could not determine package metadata for {pkg}.\n'
+ .format(pkg=self.real_name))
+ raise
+ except FileNotFoundError:
+ raise
os.chdir(current_dir)
sys.path.remove(self.tmp_extract)
for req in self.pkg_req]
# get rid of commented lines and also strip the package strings
- self.pkg_req = [item.strip() for item in self.pkg_req
- if len(item) > 0 and item[0] != '#']
+ self.pkg_req = {item.strip() for item in self.pkg_req
+ if len(item) > 0 and item[0] != '#'}
req_not_found = self.pkg_req
self.pkg_req = list(map(pkg_buildroot_name, self.pkg_req))
"""
lines = []
- filenames = ['LICENCE', 'LICENSE', 'LICENSE.RST', 'LICENSE.TXT',
- 'COPYING', 'COPYING.TXT']
+ filenames = ['LICENCE', 'LICENSE', 'LICENSE.MD', 'LICENSE.RST',
+ 'LICENCE.TXT', 'LICENSE.TXT', 'COPYING', 'COPYING.TXT']
self.license_files = list(find_file_upper_case(filenames, self.tmp_extract))
lines.append(self.__get_license_names(self.license_files))
lines.append('\thelp\n')
- help_lines = textwrap.wrap(self.metadata['info']['summary'], 62,
+ md_info = self.metadata['info']
+ help_lines = textwrap.wrap(md_info['summary'], 62,
initial_indent='\t ',
subsequent_indent='\t ')
if help_lines[-1][-1] != '.':
help_lines[-1] += '.'
- # \t + two spaces is 3 char long
- help_lines.append('')
- help_lines.append('\t ' + self.metadata['info']['home_page'])
- help_lines = [x + '\n' for x in help_lines]
- lines += help_lines
+ home_page = md_info.get('home_page', None)
+
+ if not home_page:
+ project_urls = md_info.get('project_urls', None)
+ if project_urls:
+ home_page = project_urls.get('Homepage', None)
+
+ if home_page:
+ # \t + two spaces is 3 char long
+ help_lines.append('')
+ help_lines.append('\t ' + home_page)
+ help_lines = [x + '\n' for x in help_lines]
+ lines += help_lines
with open(path_to_config, 'w') as config_file:
config_file.writelines(lines)
try:
package.load_setup()
except ImportError as err:
- if 'buildutils' in err.message:
+ if 'buildutils' in str(err):
print('This package needs buildutils')
+ continue
else:
- raise
- continue
- except AttributeError as error:
+ try:
+ package.load_pyproject()
+ except Exception:
+ raise
+ except (AttributeError, KeyError) as error:
print('Error: Could not install package {pkg}: {error}'.format(
pkg=package.real_name, error=error))
continue