--- setup.py.orig 2020-03-22 22:04:03 UTC +++ setup.py @@ -23,328 +23,7 @@ import setuptools -HAS_DIST_INFO_CMD = False -try: - import setuptools.command.dist_info - - HAS_DIST_INFO_CMD = True -except ImportError: - """Setuptools version is too old.""" - - -ALL_STRING_TYPES = tuple(map(type, ('', b'', u''))) -MIN_NATIVE_SETUPTOOLS_VERSION = 34, 4 -"""Minimal setuptools having good read_configuration implementation.""" - -# Patch version can be a non integer value, like 'post20190705' -RUNTIME_SETUPTOOLS_VERSION = tuple(map(int, setuptools.__version__.split('.')[:2])) -"""Setuptools imported now.""" - -READ_CONFIG_SHIM_NEEDED = RUNTIME_SETUPTOOLS_VERSION < MIN_NATIVE_SETUPTOOLS_VERSION - - -def str_if_nested_or_str(s): - """Turn input into a native string if possible.""" - if isinstance(s, ALL_STRING_TYPES): - return str(s) - if isinstance(s, (list, tuple)): - return type(s)(map(str_if_nested_or_str, s)) - if isinstance(s, (dict,)): - return stringify_dict_contents(s) - return s - - -def stringify_dict_contents(dct): - """Turn dict keys and values into native strings.""" - return {str_if_nested_or_str(k): str_if_nested_or_str(v) for k, v in dct.items()} - - -if not READ_CONFIG_SHIM_NEEDED: - from setuptools.config import read_configuration, ConfigOptionsHandler - import setuptools.config - import setuptools.dist - - # Set default value for 'use_scm_version' - setattr(setuptools.dist.Distribution, 'use_scm_version', False) - - # Attach bool parser to 'use_scm_version' option - class ShimConfigOptionsHandler(ConfigOptionsHandler): - """Extension class for ConfigOptionsHandler.""" - - @property - def parsers(self): - """Return an option mapping with default data type parsers.""" - _orig_parsers = super(ShimConfigOptionsHandler, self).parsers - return dict(use_scm_version=self._parse_bool, **_orig_parsers) - - def parse_section_packages__find(self, section_options): - find_kwargs = super( - ShimConfigOptionsHandler, self - ).parse_section_packages__find(section_options) - return stringify_dict_contents(find_kwargs) - - setuptools.config.ConfigOptionsHandler = ShimConfigOptionsHandler -else: - """This is a shim for setuptools': operator.gt, - '<': operator.lt, - '>=': operator.ge, - '<=': operator.le, - '==': operator.eq, - '!=': operator.ne, - '': operator.eq, - }.items(), - key=lambda i: len(i[0]), - reverse=True, - ) - ) - - def is_decimal(s): - return type(u'')(s).isdecimal() - - conditions = map(str.strip, python_requires.split(',')) - for c in conditions: - for op_sign, op_func in sorted_operators_map: - if not c.startswith(op_sign): - continue - raw_ver = itertools.takewhile( - is_decimal, c[len(op_sign) :].strip().split('.') - ) - ver = tuple(map(int, raw_ver)) - yield op_func, ver - break - - def validate_required_python_or_fail(python_requires=None): - if python_requires is None: - return - - python_version = sys.version_info - preds = parse_predicates(python_requires) - for op, v in preds: - py_ver_slug = python_version[: max(len(v), 3)] - condition_matches = op(py_ver_slug, v) - if not condition_matches: - raise RuntimeError( - "requires Python '{}' but the running Python is {}".format( - python_requires, '.'.join(map(str, python_version[:3])) - ) - ) - - def verify_required_python_runtime(s): - @functools.wraps(s) - def sw(**attrs): - try: - validate_required_python_or_fail(attrs.get('python_requires')) - except RuntimeError as re: - sys.exit('{} {!s}'.format(attrs['name'], re)) - return s(**attrs) - - return sw - - setuptools.setup = ignore_unknown_options(setuptools.setup) - setuptools.setup = verify_required_python_runtime(setuptools.setup) - - try: - from configparser import ConfigParser, NoSectionError - except ImportError: - from ConfigParser import ConfigParser, NoSectionError - - ConfigParser.read_file = ConfigParser.readfp - - def maybe_read_files(d): - """Read files if the string starts with `file:` marker.""" - FILE_FUNC_MARKER = 'file:' - - d = d.strip() - if not d.startswith(FILE_FUNC_MARKER): - return d - descs = [] - for fname in map(str.strip, str(d[len(FILE_FUNC_MARKER) :]).split(',')): - with io.open(fname, encoding='utf-8') as f: - descs.append(f.read()) - return ''.join(descs) - - def cfg_val_to_list(v): - """Turn config val to list and filter out empty lines.""" - return list(filter(bool, map(str.strip, str(v).strip().splitlines()))) - - def cfg_val_to_dict(v): - """Turn config val to dict and filter out empty lines.""" - return dict( - map( - lambda l: list(map(str.strip, l.split('=', 1))), - filter(bool, map(str.strip, str(v).strip().splitlines())), - ) - ) - - def cfg_val_to_primitive(v): - """Parse primitive config val to appropriate data type.""" - return json.loads(v.strip().lower()) - - def read_configuration(filepath): - """Read metadata and options from setup.cfg located at filepath.""" - cfg = ConfigParser() - with io.open(filepath, encoding='utf-8') as f: - cfg.read_file(f) - - md = dict(cfg.items('metadata')) - for list_key in 'classifiers', 'keywords', 'project_urls': - try: - md[list_key] = cfg_val_to_list(md[list_key]) - except KeyError: - pass - try: - md['long_description'] = maybe_read_files(md['long_description']) - except KeyError: - pass - opt = dict(cfg.items('options')) - for list_key in 'include_package_data', 'use_scm_version', 'zip_safe': - try: - opt[list_key] = cfg_val_to_primitive(opt[list_key]) - except KeyError: - pass - for list_key in 'scripts', 'install_requires', 'setup_requires': - try: - opt[list_key] = cfg_val_to_list(opt[list_key]) - except KeyError: - pass - try: - opt['package_dir'] = cfg_val_to_dict(opt['package_dir']) - except KeyError: - pass - try: - opt_package_data = dict(cfg.items('options.package_data')) - if not opt_package_data.get('', '').strip(): - opt_package_data[''] = opt_package_data['*'] - del opt_package_data['*'] - except (KeyError, NoSectionError): - opt_package_data = {} - try: - opt_extras_require = dict(cfg.items('options.extras_require')) - opt['extras_require'] = {} - for k, v in opt_extras_require.items(): - opt['extras_require'][k] = cfg_val_to_list(v) - except NoSectionError: - pass - opt['package_data'] = {} - for k, v in opt_package_data.items(): - opt['package_data'][k] = cfg_val_to_list(v) - try: - opt_exclude_package_data = dict(cfg.items('options.exclude_package_data')) - if ( - not opt_exclude_package_data.get('', '').strip() - and '*' in opt_exclude_package_data - ): - opt_exclude_package_data[''] = opt_exclude_package_data['*'] - del opt_exclude_package_data['*'] - except NoSectionError: - pass - else: - opt['exclude_package_data'] = {} - for k, v in opt_exclude_package_data.items(): - opt['exclude_package_data'][k] = cfg_val_to_list(v) - cur_pkgs = opt.get('packages', '').strip() - if '\n' in cur_pkgs: - opt['packages'] = cfg_val_to_list(opt['packages']) - elif cur_pkgs.startswith('find:'): - opt_packages_find = stringify_dict_contents( - dict(cfg.items('options.packages.find')) - ) - opt['packages'] = setuptools.find_packages(**opt_packages_find) - return {'metadata': md, 'options': opt} - - -def cut_local_version_on_upload(version): - """Generate a PEP440 local version if uploading to PyPI.""" - import os - import setuptools_scm.version # only present during setup time - - IS_PYPI_UPLOAD = os.getenv('PYPI_UPLOAD') == 'true' # set in tox.ini - return ( - '' - if IS_PYPI_UPLOAD - else setuptools_scm.version.get_local_node_and_date(version) +if __name__ == "__main__": + setuptools.setup( + use_scm_version=True, setup_requires=["setuptools_scm"], ) - - -if HAS_DIST_INFO_CMD: - - class patched_dist_info(setuptools.command.dist_info.dist_info): - def run(self): - self.egg_base = str_if_nested_or_str(self.egg_base) - return setuptools.command.dist_info.dist_info.run(self) - - -declarative_setup_params = read_configuration('setup.cfg') -"""Declarative metadata and options as read by setuptools.""" - - -setup_params = {} -"""Explicit metadata for passing into setuptools.setup() call.""" - -setup_params = dict(setup_params, **declarative_setup_params['metadata']) -setup_params = dict(setup_params, **declarative_setup_params['options']) - -if HAS_DIST_INFO_CMD: - setup_params['cmdclass'] = {'dist_info': patched_dist_info} - -setup_params['use_scm_version'] = {'local_scheme': cut_local_version_on_upload} - -# Patch incorrectly decoded package_dir option -# ``egg_info`` demands native strings failing with unicode under Python 2 -# Ref https://github.com/pypa/setuptools/issues/1136 -setup_params = stringify_dict_contents(setup_params) - - -__name__ == '__main__' and setuptools.setup(**setup_params)