From 448df20b996d1dbd25d7e27fab150242914dd4eb Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Tue, 11 Jun 2024 08:42:48 -0400 Subject: [PATCH 1/3] WIP: ENH: Add script to migrate setup.py to pyproject.toml Contains a few assumptions, but will generate a good starting point for most cases. --- setup-py-to-pyproject-toml.py | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100755 setup-py-to-pyproject-toml.py diff --git a/setup-py-to-pyproject-toml.py b/setup-py-to-pyproject-toml.py new file mode 100755 index 0000000..0691d34 --- /dev/null +++ b/setup-py-to-pyproject-toml.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 + +# This script will convert setup.py to pyproject.toml +# for ITK remote modules. It will also update the +# itk version to 5.4.* in the dependencies section. + +import os +import re +import sys +import argparse + +def setup_py_to_pyproject_toml(setup_python_path): + if not os.path.exists(setup_python_path): + print('setup.py file not found') + sys.exit(1) + + with open(setup_python_path, 'r') as f: + setup_py = f.read() + + project_name = re.search(r'name\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) + project_version = re.search(r'version\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) + project_description = re.search(r'description\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) + project_author = re.search(r'author\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) + project_author_email = re.search(r'author_email\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) + project_url = re.search(r'url\s*=\s*r?[\'"]([^\'"]*)[\'"]', setup_py).group(1) + project_classifiers = re.findall(r'classifiers\s*=\s*\[([^\]]*)\]', setup_py, re.DOTALL) + project_classifiers = project_classifiers[0].replace('\n', '').replace(' ', '').replace('"', '').split(',') + project_packages = re.findall(r'packages\s*=\s*\[([^\]]*)\]', setup_py, re.DOTALL) + project_packages = project_packages[0].replace('\n', '').replace(' ', '').replace('"', '').split(',') + project_install = re.findall(r'install_requires\s*=\s*\[([^\]]*)\]', setup_py, re.DOTALL) + + # Load the file "./{{cookiecutter.project_name}}/pyproject.toml" as the pyproject.toml template + script_dir = os.path.dirname(os.path.realpath(__file__)) + template_file = os.path.join(script_dir, '{{cookiecutter.project_name}}', 'pyproject.toml') + with open(template_file, 'r') as f: + template = f.read() + + # Replace placeholders in the template with the extracted data + template = template.replace('{{ cookiecutter.python_package_name }}', project_name) + template = template.replace('version = "0.1.0"', f'version = "{project_version}"') + template = template.replace('{{ cookiecutter.project_short_description }}', project_description) + template = template.replace('{{ cookiecutter.full_name }}', project_author) + template = template.replace('{{ cookiecutter.email }}', project_author_email) + template = template.replace('{{ cookiecutter.download_url }}', project_url) + + setup_dirname = os.path.dirname(setup_python_path) + if os.path.exists(os.path.join(setup_dirname, 'README.md')): + template = template.replace('README.rst', 'README.md') + + deps = [eval(str(d).strip()) for d in project_install] + new_deps = [] + for dep in deps: + if '==' in dep or '>=' in dep: + if '>=' in dep: + split_dep = dep.split('>=') + else: + split_dep = dep.split('==') + if 'itk' in split_dep[0] and split_dep[1][0] == '5': + new_deps.append(f'{split_dep[0]} == 5.4.*') + else: + new_deps.append(dep) + else: + new_deps.append(dep) + new_deps_str = '' + for dep in new_deps: + new_deps_str += f' "{dep}",\n' + template = template.replace(' "itk == 5.4.*",\n', new_deps_str) + + # Write the converted data to the new pyproject.toml file + with open('pyproject.toml', 'w') as f: + f.write(template) + + +def main(): + parser = argparse.ArgumentParser(description='Convert setup.py to pyproject.toml') + parser.add_argument('setup_python_path', help='Path to the setup.py file') + args = parser.parse_args() + + setup_py_to_pyproject_toml(args.setup_python_path) + + # Remove setup.py file + os.remove(args.setup_python_path) + +if __name__ == '__main__': + main() \ No newline at end of file From 369018d11cf29b9e6192b9502a06c1105fe17af9 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Sat, 7 Sep 2024 10:09:15 -0400 Subject: [PATCH 2/3] rf: Patch setuptools/skbuild.setup() and extract exec'd metadata --- setup-py-to-pyproject-toml.py | 48 +++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/setup-py-to-pyproject-toml.py b/setup-py-to-pyproject-toml.py index 0691d34..3eda7bd 100755 --- a/setup-py-to-pyproject-toml.py +++ b/setup-py-to-pyproject-toml.py @@ -8,26 +8,42 @@ import re import sys import argparse +import runpy + + +def make_shim(): + mydict = {} + + def setup_shim(**kwargs): + mydict.update(kwargs) + + return mydict, setup_shim def setup_py_to_pyproject_toml(setup_python_path): if not os.path.exists(setup_python_path): print('setup.py file not found') sys.exit(1) - with open(setup_python_path, 'r') as f: - setup_py = f.read() - - project_name = re.search(r'name\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) - project_version = re.search(r'version\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) - project_description = re.search(r'description\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) - project_author = re.search(r'author\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) - project_author_email = re.search(r'author_email\s*=\s*[\'"]([^\'"]*)[\'"]', setup_py).group(1) - project_url = re.search(r'url\s*=\s*r?[\'"]([^\'"]*)[\'"]', setup_py).group(1) - project_classifiers = re.findall(r'classifiers\s*=\s*\[([^\]]*)\]', setup_py, re.DOTALL) - project_classifiers = project_classifiers[0].replace('\n', '').replace(' ', '').replace('"', '').split(',') - project_packages = re.findall(r'packages\s*=\s*\[([^\]]*)\]', setup_py, re.DOTALL) - project_packages = project_packages[0].replace('\n', '').replace(' ', '').replace('"', '').split(',') - project_install = re.findall(r'install_requires\s*=\s*\[([^\]]*)\]', setup_py, re.DOTALL) + import setuptools + import skbuild + capture, shim = make_shim() + setuptools.setup = shim + skbuild.setup = shim + + runpy.run_path(setup_python_path) + + # with open(setup_python_path, 'r') as f: + # setup_py = f.read() + + project_name = capture['name'] + project_version = capture['version'] + project_description = capture['description'] + project_author = capture['author'] + project_author_email = capture['author_email'] + project_url = capture['url'] + project_classifiers = capture['classifiers'] + project_packages = capture['packages'] + project_install = capture['install_requires'] # Load the file "./{{cookiecutter.project_name}}/pyproject.toml" as the pyproject.toml template script_dir = os.path.dirname(os.path.realpath(__file__)) @@ -47,7 +63,7 @@ def setup_py_to_pyproject_toml(setup_python_path): if os.path.exists(os.path.join(setup_dirname, 'README.md')): template = template.replace('README.rst', 'README.md') - deps = [eval(str(d).strip()) for d in project_install] + deps = [str(d).strip() for d in project_install] new_deps = [] for dep in deps: if '==' in dep or '>=' in dep: @@ -82,4 +98,4 @@ def main(): os.remove(args.setup_python_path) if __name__ == '__main__': - main() \ No newline at end of file + main() From 3703b11cdb24715c8834dd590b6f3fba02070055 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Sat, 7 Sep 2024 10:14:40 -0400 Subject: [PATCH 3/3] feat: Bump minor version --- setup-py-to-pyproject-toml.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup-py-to-pyproject-toml.py b/setup-py-to-pyproject-toml.py index 3eda7bd..b933848 100755 --- a/setup-py-to-pyproject-toml.py +++ b/setup-py-to-pyproject-toml.py @@ -9,6 +9,7 @@ import sys import argparse import runpy +from packaging.version import Version def make_shim(): @@ -36,7 +37,8 @@ def setup_py_to_pyproject_toml(setup_python_path): # setup_py = f.read() project_name = capture['name'] - project_version = capture['version'] + current_version = Version(capture['version']) + project_version = f'{current_version.major}.{current_version.minor + 1}.0' project_description = capture['description'] project_author = capture['author'] project_author_email = capture['author_email']