11import click
2- import os
32
43# Define a comprehensive list of valid licenses from GitHub
54VALID_LICENSES = [
87]
98
109# Define available classifiers for easier reference
11- CLASSIFIERS = {
12- "Development Status" : [
13- "1 - Planning" , "2 - Pre-Alpha" , "3 - Alpha" , "4 - Beta" , "5 - Production/Stable"
14- ],
15- "Intended Audience" : [
16- "Developers" , "End Users/Desktop" , "Education" , "Science/Research" , "System Administrators"
17- ],
18- "Programming Language" : [
19- "Python :: 3" , "Python :: 3.8" , "Python :: 3.9" , "Python :: 3.10" , "Python :: 3.11"
20- ],
21- "License" : [
22- "OSI Approved :: MIT License" , "OSI Approved :: Apache Software License" , "OSI Approved :: GPL License"
23- ],
24- }
10+ DEFAULT_CLASSIFIERS = [
11+ "Development Status :: 5 - Production/Stable" ,
12+ "Intended Audience :: Developers" ,
13+ "Programming Language :: Python :: 3" ,
14+ "License :: OSI Approved :: MIT" ,
15+ "Operating System :: OS Independent"
16+ ]
2517
2618@click .command ()
2719@click .argument ("project_name" )
2820def generate_setup (project_name ):
2921 """
30- Generate a complete setup.py file for a new Python project, asking the user for all details dynamically.
22+ Generate a complete setup.py and README.md file for a new Python project, asking the user for all details dynamically.
3123 """
32- click .echo ("Generating setup.py..." )
24+ click .echo ("Generating setup.py and README.md ..." )
3325
34- # Asking for required details with default values and handling backspace
26+ # Asking for required details
3527 version = click .prompt ("Version (e.g., 0.1.0)" , type = str , default = "0.1.0" )
36- description = click .prompt ("Short project description" , type = str )
37- long_description = click .prompt ("Long description (use content from your README.md)" , type = str )
38- author = click .prompt ("Author name" , type = str )
39- author_email = click .prompt ("Author email" , type = str )
40-
41- # Handle license validation with retries
42- while True :
43- license_type = click .prompt ("License type (e.g., MIT, Apache-2.0, GPL-3.0, BSD-3-Clause, etc.)" ,
44- type = str , default = "MIT" )
45- if license_type in VALID_LICENSES :
46- break
47- else :
48- click .echo (
49- f"Invalid license type '{ license_type } '. Please choose one of the valid licenses: { ', ' .join (VALID_LICENSES )} " )
28+ description = click .prompt ("Short project description (optional)" , type = str , default = "" )
29+ long_description = click .prompt ("Long description (optional, use content from your README.md)" , type = str , default = "" )
30+
31+ # Author info now optional
32+ author = click .prompt ("Author name (optional)" , type = str , default = "" )
33+ author_email = click .prompt ("Author email (optional)" , type = str , default = "" )
34+
35+ # Asking for license selection by index
36+ click .echo ("Select a license:" )
37+ for idx , license in enumerate (VALID_LICENSES ):
38+ click .echo (f"{ idx } . { license } " )
39+ license_idx = click .prompt ("License (Enter the index number)" , type = int , default = 0 )
40+ license_type = VALID_LICENSES [license_idx ]
5041
5142 python_version = click .prompt ("Minimum Python version required (e.g., 3.8)" , type = str , default = "3.8" )
5243
@@ -58,76 +49,74 @@ def generate_setup(project_name):
5849 type = str )
5950 test_dependencies = [dep .strip () for dep in test_dependencies .split ("," ) if dep .strip ()]
6051
61- # Asking for URLs
62- project_url = click .prompt ("Project URL (e.g., GitHub URL )" , type = str )
63- bug_tracker_url = click .prompt ("Bug tracker URL" , type = str )
64- documentation_url = click .prompt ("Documentation URL" , type = str )
52+ # URLs now optional
53+ project_url = click .prompt ("Project URL (optional )" , type = str , default = "" )
54+ bug_tracker_url = click .prompt ("Bug tracker URL (optional) " , type = str , default = "" )
55+ documentation_url = click .prompt ("Documentation URL (optional) " , type = str , default = "" )
6556
66- # Asking for classifiers (optional but recommended)
67- click .echo ("Select 'Development Status' (e.g., 1 - Planning, 5 - Production/Stable):" )
68- development_status = click .prompt (
69- "Development Status" , type = click .Choice (CLASSIFIERS ["Development Status" ]), default = "1 - Planning"
70- )
57+ # Ask if the user wants to specify classifiers
58+ click .echo ("Would you like to specify 'Development Status', 'Intended Audience', and 'Programming Language'?" )
59+ use_classifiers = click .confirm ("Specify classifiers?" , default = False )
7160
72- click .echo ("Select 'Intended Audience' (e.g., Developers, End Users/Desktop):" )
73- audience = click .prompt (
74- "Intended Audience" , type = click .Choice (CLASSIFIERS ["Intended Audience" ]), default = "Developers"
75- )
61+ classifiers = DEFAULT_CLASSIFIERS
62+ if use_classifiers :
63+ # Development Status
64+ development_status = click .prompt ("Select 'Development Status' (e.g., 1 - Planning, 2 - Pre-Alpha, etc.)" , type = str , default = "5 - Production/Stable" )
65+ classifiers [0 ] = f"Development Status :: { development_status } "
7666
77- click .echo ("Select 'Programming Language' (e.g., Python 3.8, Python 3.9):" )
78- language = click .prompt (
79- "Programming Language" , type = click .Choice (CLASSIFIERS ["Programming Language" ]), default = "Python :: 3.8"
80- )
67+ # Intended Audience
68+ audience = click .prompt ("Select 'Intended Audience' (e.g., Developers, Education, etc.)" , type = str , default = "Developers" )
69+ classifiers [1 ] = f"Intended Audience :: { audience } "
70+
71+ # Programming Language
72+ language = click .prompt ("Select 'Programming Language' (e.g., Python :: 3)" , type = str , default = "Python :: 3" )
73+ classifiers [2 ] = f"Programming Language :: { language } "
74+
75+ # Prepare the content for the README.md file
76+ readme_content = f"# { project_name } \n \n { long_description if long_description else 'Project description' } \n "
8177
8278 # Prepare the content for the setup.py file
8379 setup_content = f"""
8480from setuptools import setup, find_packages
8581
8682VERSION = "{ version } " # Version of your package
87- DESCRIPTION = '{ description } ' # Short description
83+ DESCRIPTION = '{ description if description else "Project description" } ' # Short description
8884
8985# Long description of the project (can be pulled from README.md)
90- LONG_DESCRIPTION = '''{ long_description } '''
86+ LONG_DESCRIPTION = '''{ long_description if long_description else 'Detailed project description from README.md' } '''
9187
9288setup(
9389 name="{ project_name } ", # Name of your package
9490 version=VERSION, # Package version
95- author="{ author } ", # Author name
96- author_email="{ author_email } ", # Author's email
91+ author="{ author if author else '' } ", # Author name
92+ author_email="{ author_email if author_email else '' } ", # Author's email
9793 description=DESCRIPTION, # Short description
9894 long_description=LONG_DESCRIPTION, # Detailed description from README.md
9995 long_description_content_type="text/markdown", # Format of the long description
100- url="{ project_url } ", # URL to the project's GitHub page
96+ url="{ project_url if project_url else '' } ", # URL to the project's GitHub page
10197 packages=find_packages(), # Automatically find all packages in the directory
102- classifiers=[ # List of classifiers to categorize your package
103- "Development Status :: { development_status } ",
104- "Intended Audience :: { audience } ",
105- "Programming Language :: { language } ",
106- "License :: OSI Approved :: { license_type } ",
107- "Operating System :: OS Independent",
108- ],
98+ classifiers={ classifiers } , # List of classifiers to categorize your package
10999 python_requires=">={ python_version } ", # Minimum Python version required
110100 install_requires={ dependencies } , # List of dependencies
111101 setup_requires=["pytest-runner"], # For running tests during installation
112102 tests_require={ test_dependencies } , # Specify dependencies needed for running tests
113103 license="{ license_type } ", # License under which the project is released
114104 project_urls={{ # Additional URLs related to your project
115- "Source Code": "{ project_url } ",
116- "Bug Tracker": "{ bug_tracker_url } ",
117- "Documentation": "{ documentation_url } ",
105+ "Source Code": "{ project_url } "
106+ "Bug Tracker": "{ bug_tracker_url } "
107+ "Documentation": "{ documentation_url } "
118108 }},
119109)
120-
121110"""
122111
123- # Ensure the project folder exists, and create the setup.py file
124- if not os . path . exists ( project_name ) :
125- os . makedirs ( project_name )
112+ # Create the README.md and setup.py files in the current directory
113+ with open ( "README.md" , "w" ) as readme_file :
114+ readme_file . write ( readme_content )
126115
127- with open (f" { project_name } / setup.py" , "w" ) as f :
128- f .write (setup_content )
116+ with open (" setup.py" , "w" ) as setup_file :
117+ setup_file .write (setup_content )
129118
130- print (f"setup.py has been successfully generated for project '{ project_name } '." )
119+ print (f"README.md and setup.py have been successfully generated for project '{ project_name } '." )
131120
132121if __name__ == "__main__" :
133122 generate_setup ()
0 commit comments