11import os
22import shutil
3+ import tomli
4+ import tomli_w
35
46
57def remove (filepath : str ):
@@ -19,6 +21,147 @@ def delete_line_in_file(filepath: str, line_starts_with: str):
1921 f .truncate ()
2022
2123
24+ def read_toml (filepath : str ):
25+ """Read a TOML file."""
26+ with open (filepath , "rb" ) as f :
27+ return tomli .load (f )
28+
29+
30+ def update_pyproject_toml ():
31+ """Update pyproject.toml with project config and dependencies."""
32+ project_config = read_toml ("project_config.toml" )
33+ dependencies = read_toml ("dependencies.toml" )
34+
35+ # Read the current pyproject.toml
36+ with open ("pyproject.toml" , "rb" ) as f :
37+ pyproject = tomli .load (f )
38+
39+ package_manager = "{{cookiecutter.package_manager}}" .lower ()
40+
41+ # Add project configuration
42+ if package_manager == "poetry" :
43+ # Poetry uses tool.poetry for project metadata
44+ pyproject ["tool" ] = pyproject .get ("tool" , {})
45+ pyproject ["tool" ]["poetry" ] = {
46+ "name" : project_config ["project" ]["name" ],
47+ "version" : project_config ["project" ]["version" ],
48+ "description" : project_config ["project" ]["description" ],
49+ "authors" : project_config ["project" ]["authors" ],
50+ "license" : project_config ["project" ]["license" ],
51+ "readme" : project_config ["project" ]["readme" ],
52+ "homepage" : project_config ["project" ]["homepage" ],
53+ "classifiers" : project_config ["project" ]["classifiers" ],
54+ "packages" : [project_config ["project" ]["package_dir" ]],
55+ "exclude" : project_config ["project" ]["exclude" ],
56+ }
57+
58+ # Add dependencies
59+ pyproject ["tool" ]["poetry" ]["dependencies" ] = {"python" : f"^{ project_config ['project' ]['python_version' ]} " }
60+ for name , version in dependencies ["dependencies" ].items ():
61+ pyproject ["tool" ]["poetry" ]["dependencies" ][name ] = f"^{ version } "
62+
63+ # Add dev dependencies
64+ pyproject ["tool" ]["poetry" ].setdefault ("group" , {})
65+ pyproject ["tool" ]["poetry" ]["group" ]["dev" ] = {"optional" : True , "dependencies" : {}}
66+ for name , version in dependencies ["dev-dependencies" ].items ():
67+ if isinstance (version , dict ):
68+ # Handle complex dependencies like black = {version = "23.7.0", extras = ["jupyter"]}
69+ pyproject ["tool" ]["poetry" ]["group" ]["dev" ]["dependencies" ][name ] = {
70+ "version" : f"^{ version ['version' ]} " ,
71+ "extras" : version .get ("extras" , [])
72+ }
73+ else :
74+ pyproject ["tool" ]["poetry" ]["group" ]["dev" ]["dependencies" ][name ] = "*" if version == "*" else f"^{ version } "
75+
76+ # Add poetry-specific tool tasks
77+ pyproject ["tool" ]["poe" ]["tasks" ]["_poetry_install_sort_plugin" ] = "poetry self add poetry-plugin-sort"
78+ pyproject ["tool" ]["poe" ]["tasks" ]["_poetry_sort" ] = "poetry sort"
79+ pyproject ["tool" ]["poe" ]["tasks" ]["format" ] = ["_ruff_format" , "_ruff_format_nb" , "_black_format" , "_poetry_install_sort_plugin" , "_poetry_sort" ]
80+
81+ elif package_manager == "uv" :
82+ # UV uses standard project metadata
83+ pyproject ["project" ] = {
84+ "name" : project_config ["project" ]["name" ],
85+ "version" : project_config ["project" ]["version" ],
86+ "description" : project_config ["project" ]["description" ],
87+ "authors" : [{"name" : author .split ("<" )[0 ].strip (), "email" : author .split ("<" )[1 ].strip (">" )}
88+ for author in project_config ["project" ]["authors" ]],
89+ "license" : {"text" : project_config ["project" ]["license" ]},
90+ "readme" : project_config ["project" ]["readme" ],
91+ "requires-python" : f">={ project_config ['project' ]['python_version' ]} " ,
92+ "classifiers" : project_config ["project" ]["classifiers" ],
93+ }
94+
95+ # Add project URLs
96+ pyproject ["project" ]["urls" ] = {"Homepage" : project_config ["project" ]["homepage" ]}
97+
98+ # Add dependencies
99+ pyproject ["project" ]["dependencies" ] = []
100+ for name , version in dependencies ["dependencies" ].items ():
101+ pyproject ["project" ]["dependencies" ].append (f"{ name } >={ version } " )
102+
103+ # Add dev dependencies
104+ pyproject ["project" ]["optional-dependencies" ] = {"dev" : []}
105+ for name , version in dependencies ["dev-dependencies" ].items ():
106+ if isinstance (version , dict ):
107+ # Handle complex dependencies
108+ ver_str = version .get ("version" , "*" )
109+ if "extras" in version :
110+ extras = ',' .join (version ["extras" ])
111+ pyproject ["project" ]["optional-dependencies" ]["dev" ].append (f"{ name } [{ extras } ]>={ ver_str } " )
112+ else :
113+ pyproject ["project" ]["optional-dependencies" ]["dev" ].append (f"{ name } >={ ver_str } " )
114+ else :
115+ if version == "*" :
116+ pyproject ["project" ]["optional-dependencies" ]["dev" ].append (name )
117+ else :
118+ pyproject ["project" ]["optional-dependencies" ]["dev" ].append (f"{ name } >={ version } " )
119+
120+ elif package_manager == "pixi" :
121+ # Pixi uses tool.pixi for dependencies
122+ pyproject ["project" ] = {
123+ "name" : project_config ["project" ]["name" ],
124+ "version" : project_config ["project" ]["version" ],
125+ "description" : project_config ["project" ]["description" ],
126+ "authors" : [{"name" : author .split ("<" )[0 ].strip (), "email" : author .split ("<" )[1 ].strip (">" )}
127+ for author in project_config ["project" ]["authors" ]],
128+ "license" : {"text" : project_config ["project" ]["license" ]},
129+ "readme" : project_config ["project" ]["readme" ],
130+ "requires-python" : f">={ project_config ['project' ]['python_version' ]} " ,
131+ "classifiers" : project_config ["project" ]["classifiers" ],
132+ }
133+
134+ # Add project URLs
135+ pyproject ["project" ]["urls" ] = {"Homepage" : project_config ["project" ]["homepage" ]}
136+
137+ # Add dependencies
138+ pyproject ["tool" ] = pyproject .get ("tool" , {})
139+ pyproject ["tool" ]["pixi" ] = {}
140+ pyproject ["tool" ]["pixi" ]["dependencies" ] = {}
141+ for name , version in dependencies ["dependencies" ].items ():
142+ pyproject ["tool" ]["pixi" ]["dependencies" ][name ] = f">={ version } "
143+
144+ # Add dev dependencies
145+ pyproject ["tool" ]["pixi" ]["dev-dependencies" ] = {}
146+ for name , version in dependencies ["dev-dependencies" ].items ():
147+ if isinstance (version , dict ):
148+ # Handle complex dependencies
149+ pyproject ["tool" ]["pixi" ]["dev-dependencies" ][name ] = {
150+ "version" : f">={ version ['version' ]} " ,
151+ "extras" : version .get ("extras" , [])
152+ }
153+ else :
154+ pyproject ["tool" ]["pixi" ]["dev-dependencies" ][name ] = "*" if version == "*" else f">={ version } "
155+
156+ # Write the updated pyproject.toml
157+ with open ("pyproject.toml" , "wb" ) as f :
158+ tomli_w .dump (pyproject , f )
159+
160+ # Clean up the template files
161+ remove ("project_config.toml" )
162+ remove ("dependencies.toml" )
163+
164+
22165if "{{cookiecutter.include_readthedocs_yaml}}" .lower () != "y" :
23166 remove (".readthedocs.yaml" )
24167
@@ -27,9 +170,12 @@ def delete_line_in_file(filepath: str, line_starts_with: str):
27170 remove ("config.json" )
28171 remove ("docs/02_notebooks/02_config_example.ipynb" )
29172 remove ("data" )
30- delete_line_in_file ("pyproject.toml" , "accsr" )
31173 delete_line_in_file (".gitignore" , "config_local.json" )
32174
175+ # Update pyproject.toml with project config and dependencies
176+ update_pyproject_toml ()
177+
178+ # Initialize git repository
33179return_code = os .system ("""
34180echo "Initializing your new project in $(pwd)."
35181
0 commit comments